home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-01-14 | 567.9 KB | 1,836 lines | [ONLN/HLX2] |
- Inside Macintosh:Imaging Apple Computer, Inc. © 1991, Apple Computer, Inc.All rights reserved.Printed in the United States of America.The Apple logo is a registered trademark of Apple Computer, Inc. Use of the “keyboard” Apple logo (Option-Shift-K) for commercial purposes without the prior written consent of Apple may constitute trademark infringement and unfair compe-tition in violation of federal and state laws.Apple Computer, Inc. 20525 Mariani Avenue Cupertino, CA 95014-6299408-996-1010 Apple, the Apple logo, APDA, AppleLink, AppleShare, AppleTalk, Apple IIGS, A/UX, EtherTalk, HyperCard, Hyper-Talk, ImageWriter, LaserWriter, LocalTalk, Mac, Macintosh, MPW, MultiFinder, SANE, and TokenTalk are registered trade-marks of Apple Computer, Inc.Apple Desktop Bus, Balloon Help, Finder, KanjiTalk, Moof, QuickDraw, ResEdit, TrueType, and Zhong-Wen Talk are trade-marks of Apple Computer, Inc.Helvetica and Times are registered trademarks of Linotype Company.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.MacPaint is a registered trade-mark of Claris Corporation.NuBus is a trademark of Texas Instruments.PostScript is a registered trade-mark, and Illustrator is a trademark, of Adobe Systems Incorporated.Sony is a registered trademark of Sony Corporation.UNIX is a registered trademark of UNIX System Laboratories, Inc.Simultaneously published in the United States and Canada.Limited Warranty on Media and ReplacementEven though Apple has reviewed this manual, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS MANUAL, ITS QUALITY, ACCURACY, MERCHANT-ABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS MANUAL IS SOLD “AS IS,” AND YOU, THE PUR-CHASER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSE-QUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS MANUAL, even if advised of the possibility of such damages. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state.The Printing ManagerIntroduction to Printing2-3Methods and Qualities of Printing2-4Page and Paper Rectangles2-4Printer Resolution2-5About the Printing Manager2-6The User’s Formatting Input2-6The Print Record and the Printing Loop2-7The Idle Procedure2-8Using the Printing Manager2-9Creating and Using the Print Record2-9Printing a Document2-10Printing From the Finder2-15Printing Each Page as a Separate Document2-15Printing From the Low-Level Interface2-16Checking for PrGeneral2-16Determining the Resolution of the Current Printer2-17Determining Page Orientation2-20Choosing Draft-Quality Printing2-21Altering the Style or Job Dialog Box2-23Writing an Idle Procedure2-25Optimizing Printing2-26Optimizing PostScript Printing2-26Providing Names of Documents Being Printed2-27Canceling or Pausing the Printing Process2-28Handling Printing Errors2-28Using Alert or Dialog Boxes to Report Errors2-28Interpreting PrGeneral Errors2-29Reference2-29Data Structures2-29TPrint 2-30TPrInfo 2-31TPrJob 2-31TPrStl 2-33TPrStatus 2-33TPrPort2-34TGnlData 2-35TGetRslBlk 2-35TSetRslBlk 2-37TDftBitsBlk 2-38TGetRotnBlk 2-38TPrDlg 2-39Routines2-40Opening and Closing the Printing Manager2-40Filling and Verifying Print Records2-41Displaying and Customizing the Printing Dialog Boxes2-43Printing2-47Optimizing Printing2-51Error Handling2-54Low-Level Routines2-56Low-Level Control Calls2-58Summary2-611The Printing ManagerThis chapter describes the theory behind and implementation of printing from the Macintosh computer to any printer: Your application draws a printed document on a printer just as it draws an image on a monitor screen. This manner of printing allows you to use the same QuickDraw routines for printing as for screen display. The chapter also describes what your application needs to do to allow the user to print on any type of printer and how you can optimize printing on different types of printers.You should use this chapter if you want your application to allow the user to print. Before reading this chapter, you should be familiar with QuickDraw’s drawing routines and the grafPort data type. You may also need to refer to the <italics\>Worldwide Software volume for information about printing text from non-Roman script systems.This chapter begins with a description of the elements of the printing environment: types of printing, page characteristics, and printer characteristics. Then it describes n printing a documentn optimizing printing performancen handling printing errorsn using picture commentsFor further information about the LaserWriter printer and how it operates, see the LaserWriter Reference, published by Addison-Wesley. For information about how PostScript works and the specifics of PostScript commands, see the PostScript Language Reference Manual, also published by Addison-Wesley. Introduction to PrintingIn order for your application to print, it sends an image to a printer, taking into account the features the printer offers, how the printer prints, and the size of the paper the user wants. Your application doesn’t have to know the kind of printer the user has chosen, because you call the same printing routines, regardless of the type of printer. These routines are translated into actual printing code by the printer resource file, which is on the user’s system. (Each type of printer has its own printer resource file.) The printer resource file contains a device driver, called the printer driver, that takes the document from the Printing Manager and sends it to the printer. One printer driver can communicate with several printers of the same type; for example, the LaserWriter printer driver can work with several LaserWriter printers on a network. Your application should be device-independent when it prints a document, so that it doesn’t rely on any one printer feature being present. For instance, the current printer the user has selected may produce laser-quality or dot-matrix type, and your application should be ready to handle both. The Printing Manager takes much of the work out of coming up with a single way to handle all possible printer environments. However, while you shouldn’t depend on any feature being present, there are a few things about printers of which you should be aware and which you can use to optimize printing: the method of printing the user wants, the size of the paper on which the user will print the document, and the resolution of the printer.Methods and Qualities of PrintingThere are two basic methods of printing documents: immediate and deferred. The Printing Manager chooses which method to use by determining the capabilities of the current printer and using the printing preferences selected by the user. The two printing methods are implemented in different ways for different printers. Immediate printing means that the document prints as your application draws it in the printing grafPort. Your QuickDraw drawing calls are converted directly into command codes the printer driver understands and uses to print the document. Your printing code, the data to be printed, and the printer driver code are all present in memory. Immediate printing is also known as draft printing. With deferred printing, the Printing Manager writes out a representation of the document’s printed image to a disk file (called a spool file) or possibly to memory; this information is then converted into a bit image and printed. Deferred printing is also known as spool printing. The internal format of spool files is private to the Printing Manager and may vary from one printer to another. You should not attempt to determine the format of these files or use <36pt\>\x12 <8bat\>u There are also two qualities of printing: high-quality and draft-quality. High-quality printing produces documents that use all of the fonts and formatting that the user has included. Draft-quality printing produces quick, low-quality drafts of text documents that are printed straight down the page from top to bottom and left to right. Generally, only text is printed using the printer’s internal fonts, without formatting. n The LaserWriter printer produces only high-quality output. n The ImageWriter printer can produce high-quality or draft-quality output. Deferred printing produces standard or high-quality printing; immediate printing produces draft-quality printing. Page and Paper RectanglesThere are two sizes to consider when printing a document: the physical size of the paper, and the area on the paper that the printer can use to format the document, which should be smaller than the physical sheet of paper to account for margins. The page rectangle represents the boundaries of the printable page. Its top left corner always has the coordinates (0,0); the coordinates of the bottom right corner give the maximum page height and width attainable on the given printer, in dots. The paper rectangle gives the physical paper size, defined in the same coordinate system as the page rectangle. Thus, the top left coordinates of the paper rectangle are typically negative and its bottom right coordinates are greater than those of the page rectangle. The relationship of the two rectangles is shown in Figure 1-1. Page and paper rectangles Your application should always use the page rectangle sizes provided by the printer driver and should not attempt to change them or add new ones. If your application supports page size other than those provided by the printer driver for the current printer, you risk compatibility problems with Apple’s printer drivers and those of third-party printer makers. When formatting a page for printing, remember that in general the screen is wider than it is tall, whereas the page is taller than it is wide. You should use the page rectangle size that the user has chosen in order to format the document. (See “The Print Record and the Printing Loop” on page 1-7 for more information about where to find the user’s choices for formatting the document.) Printer Resolution Resolution is the degree of clarity of your display device, whether a screen or a printer. A monitor has better resolution than a television set used as a monitor, and a laser printer has better resolution than a dot-matrix printer. Resolution is usually specified in dots per inch, or dpi, in the X and Y directions. The higher the value, the finer the detail of the image. A printer supports either discrete or variable resolution. Discrete resolution means that the application can choose from a limited number of resolutions predefined by the printer driver. For example, the ImageWriter printer supports four discrete resolutions: 72 ¥ 72 dpi, 144 ¥ 144 dpi, 80 ¥ 72 dpi, and 160 ¥ 144 dpi. Variable resolution means the application can define any resolution within a range bounded by maximum and minimum values. The LaserWriter printer driver supports variable resolution within a range from 25 dpi to 1500 dpi in both the X and Y directions. (However, a LaserWriter printer that uses PostScript supports a maximum resolution of 300 ¥ 300 dpi. Some other PostScript devices that use the LaserWriter printer driver can achieve higher resolutions, up to the maximum supported by the LaserWriter driver.) In order to print, your application does not need to check the resolutions available or set the resolution. However, if your application does factor in possible resolutions, it can obtain the best quality output from a printer choosing equal resolutions for the X and Y directions. Some devices support X and Y resolutions that are not equal, but using this type of resolution usually results in a distortion of the printed image. For information on how to determine the available resolution or resolutions for the currently selected printer, see “Determining the Resolution of the Current Printer” on page 1-17. About the Printing ManagerIn order to print, your application first uses the Printing Manager to open the printer driver. You then prepare the document for printing by formatting it as necessary for the page size that the user has selected. When you print, you draw the document using QuickDraw routines into the printing grafPort. The Printing Manager gives you a printing grafPort when you open a document for printing. The printing grafPort data type is a QuickDraw grafPort with additional fields that customize it for printing. (You must check for the type of grafPort data type, because it may be a color grafPort data type.) The TPPrPort data type defines the printing grafPort record. TYPE TPPrPort = ^TPrPort; TPrPort = RECORD gPort: GrafPort; {grafPort to draw in } gProcs: QDProcs; {drawing routines of the printer driver} { more fields for internal use }END;You print text and graphics by drawing into this port with QuickDraw calls, just as if you were drawing on the screen. (The printer driver installs its own versions of QuickDraw’s low-level drawing routines in the gProcs field of the printing grafPort data type, causing your higher-level QuickDraw calls to drive the printer instead of drawing on the screen. You should store your versions of QuickDraw routines in the gProcs field of the gPort field of the grafPort data type.) Once you have drawn the document in the printing grafPort, the printer driver takes over, translating the QuickDraw calls for the printer. The printer itself does nothing except draw the document on a page, exactly as the printer driver directs it. The User’s Formatting InputThe user gives you the information on how to format and print a document—for example, the dimensions of the page, the pages of the document that should be printed, the number of copies—through two standard dialog boxes: the style dialog box and the job dialog box. The style dialog box lets the user specify the dimensions of the paper rectangle and any options that affect the image to be printed, which is the information you need to format the document. Your application can customize the style dialog box to ask for additional information. Figure 1-2 shows a sample style dialog box for the LaserWriter SC printer. Your application should present the style dialog box when the user chooses the Page Setup command from the File menu. A sample style dialog box The job dialog box lets the user specify how to print the document this time, such as the print quality (whether high-quality or draft-quality), the type of paper feed (such as paper tray or manual), the range of pages to print, and the number of copies. Your application can customize the job dialog box to ask for information beyond these topics. Figure 1-3 shows a sample job dialog box for the LaserWriter SC printer. Your application should present the job dialog box when the user chooses the Print command from the File menu. A sample job dialog box The Print Record and the Printing LoopIn order to print a document, you need a print record. The print record, of type TPrint (see page 1-30) contains the Printing Manager version, information about the printer (such as its resolution in dpi), the dimensions of the paper rectangle, and the specifications the user made in the style and job dialog boxes. The print record has several subrecords. The printer information subrecord, of type TPrInfo (see page 1-31), gives you the information needed for page composition, including the vertical and horizontal resolution of the printer in dpi and the boundaries of the page rectangle (which is determined in the style dialog box, discussed on page 1-6). The printing job subrecord, of type TPrJob (see page 1-31), gives you information about a particular printing job; for instance, the first and last pages to be printed, the number of copies, and the method of printing the Printing Manager will use. The user sets its contents using the job dialog box. Your application should not change the data in the print record—be sure to use the standard dialog boxes to set this information. The only fields you may need to set directly are some containing optional information in the printing job subrecord (for example, the pointer to the idle procedure). Attempting to set other values directly in the print record can produce unexpected results. <36pt\>\x12 <8bat\>s Your application should contain a printing loop, which is where all the printing needs are handled, including presenting the job dialog box and determining the range of pages to be printed. In the printing loop, you open the Printing Manager, initialize a grafPort data type for the document (“open” the document), and calculate the bounding rectangle for one page of the document (“open” a page). Each page needs to be opened and closed before you can handle any subsequent page of the document, so that you can determine exactly how much information of the document fits on each page. When you are through with the pages, you then close the document and close the Printing Manager before ending. You must always issue the closing routine that matches any opening routines (for instance, PrOpenDoc and PrCloseDoc), even if the user has aborted printing or if an error is returned by the open calls. An example of a printing loop is shown in Listing 1-1 on page 1-12.The Idle ProcedureYou can designate an idle procedure to be run whenever the Printing Manager has directed output to the printer. It stops running once the entire document has been sent to the printer and does not run while the printer actually prints. The idle procedure takes no parameters and returns no result; the Printing Manager simply runs it at every opportunity. Some applications use the idle procedure to produce a dialog box, such as the one in Figure 1-4, on the screen that informs the user that the document is printing and the Command-period command will cancel printing. A sample idle procedureIf you don’t designate a idle procedure, the Printing Manager uses its default idle procedure. The printing job subrecord of the print record contains a pointer to the idle procedure in the PIdleProc field. For more information about what to be aware of when creating a idle procedure, see “Writing an Idle Procedure” on page 1-25. Using the Printing ManagerYou can use the Printing Manager to print documents, to display and alter the printing dialog boxes, and to handle printing errors. The Printing Manager provides routines that give your application device-independent control over the printing process. All printable documents must have a print record. Each print record contains information about page size, number of copies requested, and the pages the user wants printed, among other things. You should store this print record with the document so that you can save the user’s preferences. To print a user’s document, first create or validate the document’s print record. Then you should have a printing loop that handles printing and checks for printing errors at every step. You should never assume what type of printer has been selected; that is, your application should always be able to print to any type of printer. To use the Printing Manager, you must first initialize QuickDraw, the Font Manager, the Window Manager, the Menu Manager, TextEdit, and the Dialog Manager. The first Printing Manager routine to call is PrOpen; the last routine to call is PrClose.Creating and Using the Print RecordIn order to print a document, you need a valid print record that is formatted for the current versions of the Printing Manager and the printer driver. The print record has information such as the vertical and horizontal resolution of the printer in dpi, the boundaries of the page rectangle, the number of copies, and the method of printing the user has requested.To create a new print record, you must first create a handle to it with the Memory Manager function NewHandle. You then must fill the fields of the record with appropriate values; for example, use PrintDefault to set the fields to the default values stored in the printer driver. prRecHdl := THPrint(NewHandle(SIZEOF(TPrint)));PrintDefault(prRecHdl);You can use an existing print record (for instance, one saved with a document). If you use an existing print record, be sure to call the PrValidate function before using the print record to make sure it’s valid for the current version of the Printing Manager and for the currently installed printer. You should save the print record when the user closes the document. This saves any preferences that the user has selected for printing that document, such as orientation of the page or page size. Many of the fields in the print record are reserved for use by Apple and they are likely to change without notice. Also, every printer driver uses the fields of the print record differently. In order to maintain compatibility with the Printing Manager, there are some guidelines you should follow:n Do not test for the contents of undocumented fields.n Do not set fields in the print record directly.n You should use the existing print dialog boxes, or, if you want to customize them, alter them only as recommended in “Altering the Style or Job Dialog Box” on page 1-23.Printing a DocumentThe printing loop calls all the Printing Manager routines necessary to print a document. The general printing loop shown in Listing 1-1 is an extremely broad example of a printing loop—for example, the code does not optimize for the type of printer being used nor for the material being printed (text, graphics, or a mixture of both). However, it does cover the major aspects of what is needed in a printing loop: the balance of open and close calls, determining page count, and providing support for documents longer than the maximum named by the Printing Manager constant iPFMaxPgs. The printing loop starts by getting a pointer to the current grafPort. Then it calls a routine, MyUnloadTheWorld, that swaps out code segments not required during printing. (The specifics of this routine are left up to the individual application.) At this point, it opens the Printing Manager, printer driver, and printer resource file for use by calling PrOpen.The loop saves the driver’s resource file so that if your idle procedure changes the resource chain in any way, the driver does not lose its resources. (See “Writing an Idle Procedure” on page 1-25.) The PrintDefault procedure fills the print record with the default values specified by the current printer driver; the user may change these values with the style and job dialog boxes. In order to print the document, you must divide the data into sections that fit within the page rectangle dimensions set by the user in the style dialog box and stored in the rPage field of the printing job record. The MyDetermineNumOfPages function must be specific to the application, because the way the application divides up the data depends on the type of text and graphics in the document. After determining the number of pages, the printing loop presents the user with the job dialog box. The user’s responses here provide information such as the number of the copies and the page numbers of the first and last pages requested. The loop stores these values in local variables such as firstPage and lastPage. It then resets the values of the first and last pages in the printing job record as 1 and 9999 (using the constant iPrPgMax). The loop compares the values of the number of pages in the document with the last page the user requested. If the user has requested the printing loop to print page 50 of a two-page document, the printing loop resets the value of the last page to 2. This avoids printing errors later on in the loop. At this point, the loop begins the process of sending the pages off to be printed. It puts up the dialog box of the idle procedure and restores the printer driver’s resource chain. Once in the page loop, the printing loop checks to see if the size of the file is greater than the maximum number of pages that can be printed (given by the constant iPFMaxPgs). If the user has chosen immediate printing, your application can print iPFMaxPgs number of pages and then begin the printing loop again with the next section of the document. If the user has chosen deferred printing and the file is larger than iPFMaxPgs, the loop closes the document and sends the first 128 pages to a spool file to be printed. You then must go back and print the next portion of the document. You can print any number of iPFMaxPgs pages, provided you only send that many at any one time. The loop then opens a page for printing and draws the page in the printing grafPort with the MyDrawStuff procedure, the details of which are specific to the application. In this loop, the parameters contain the size of the page rectangle, the grafPort selected, and the page number to be printed. The application can use the same code to print a page of a document as it uses to draw the same page on screen. When the loop is finished printing, it closes the document. If the user has selected spool printing, you call the PrPicFile procedure, which sends the spool file to the printer driver. The printing loop then closes the Printing Manager, reports any Printing Manager errors, and resets the grafPort record to the original port. At the end of the printing loop, all open routines to the Printing Manager are balanced with close routines. This is extremely important to do, even if you stop printing because of an error. Failure to call the matching close calls can cause the Printing Manager to perform incorrectly.Note that every section of the procedure calls PrError after each Printing Manager routine. If an error is found, the loop calls a close routine (for instance, PrClose or PrCloseDoc) for any Printing Manager open routines (PrOpen or PrOpenDoc) before alerting the user of the error. You should use this approach in your own application to make sure the Printing Manager closes properly and all temporary memory is released. A sample print loop{ Below is a general print loop. The code makes no assumption about }{ what printer is being used nor does it take advantage of what's }{ being printed; text, graphics, whatever. Depending on how you }{ implement your own print loop for your application, you can make }{ it robust with print status dialogs and idle procs or simpler }{ without them. You must remember to balance the open and close }{ calls to the Printing Manager. Failure to do so can cause the }{ Printing Manager to not perform correctly. }PROCEDURE MyPrintLoop;VAR copies: Integer; firstPage: Integer; lastPage: Integer; numberOfCopies: Integer; pageNumber: Integer; printResFile: Integer; printError: Integer; numberOfPages: Integer; oldPort: GrafPtr; theStatus: TPrStatus; BEGIN GetPort(oldPort); {MyUnloadTheWorld is your routine to swap out unneeded segments that } { are not required during print time. Your print code must be in a } { separate code segment. You need to do this for memory considerations.} MyUnLoadTheWorld; PrOpen; IF (PrError = noErr) THEN BEGIN {Save the current resource file so the driver will not } { lose its resources upon return from pIdleProc.} printResFile := CurResFile; PrintDefault(gPrintRec); IF (PrError = noErr) THEN BEGIN {MyDetermineNumOfPages is your routine that determines } { the number of pages contained in the document by } { comparing the size of the document with rPage, the } { printable area for the currently selected printer. } { It returns the number of pages required to print the } { document. This routine is specific to the individual } { application.} numberOfPages := MyDetermineNumOfPages(gPrintRec^^.prInfo.rPage); IF (PrJobDialog(gPrintRec)) THEN BEGIN {Get the number of copies along with the first } { and last pages of the document that the user } { wants printed. Also, pretend you are going } { to print the entire document.} numberOfCopies := gPrintRec^^.prJob.iCopies; firstPage := gPrintRec^^.prJob.iFstPage; lastPage := gPrintRec^^.prJob.iLstPage; gPrintRec^^.prJob.iFstPage := 1; gPrintRec^^.prJob.iLstPage := iPrPgMax; {Determine the "real" number of pages contained } { in the document. Without this test, you could } { print up to iPrPgMax pages, or at least try to.} IF (numberOfPages < lastPage) THEN lastPage := numberOfPages; {Install and call your "Print Status Dialog" here. } { For example: } { printStatusDlg := GetNewDialog(257, NIL, pointer(-1)); } { gPrintRec^^.prJob.pIdleProc := @checkMyPrintDlgButton;} {Print the number of copies of the document } { requested by the user from the print job dialog.} FOR copies := 1 TO numberOfCopies DO BEGIN {Restore the printer driver's resource file.} UseResFile(printResFile); {Print the range of pages of the document } { requested by the user from the job dialog.} FOR pageNumber := firstPage TO lastPage DO BEGIN {Check for max size of spool file. If it is larger than } { a multiple of 128, then close the doc, initiate } { printing, and reopen the doc. Notice that the } { IF statement is always true the first time through, } { thus ensuring the doc is always opened.} IF (pageNumber - firstPage) MOD iPFMaxPgs = 0 THEN BEGIN IF pageNumber <> firstPage THEN BEGIN PrCloseDoc(gPrinterPort); IF (gPrintRec^^.prJob.bJDocLoop = bSpoolLoop) AND (PrError = noErr) THEN PrPicFile(gPrintRec, NIL, NIL, NIL, theStatus); END; gPrinterPort := PrOpenDoc(gPrintRec, NIL, NIL); END; IF (PrError = noErr) THEN BEGIN PrOpenPage(gPrinterPort, NIL); IF (PrError = noErr) THEN {The rPage field of the prInfo record is the } { printable area for the currently selected } { printer. If you send the current port, your } { app can use the same routine to draw to} { the screen and the printer's GrafPort. } MyDrawStuff (gPrintRec^^.prInfo.rPage, GrafPtr(gPrinterPort), pageNumber); PrClosePage(gPrinterPort); END; END; PrCloseDoc(gPrinterPort); IF (gPrintRec^^.prJob.bJDocLoop = bSpoolLoop) AND (PrError = noErr) THEN PrPicFile(gPrintRec, NIL, NIL, NIL, theStatus); END; END; END; END; {Get the error before PrClose or the error disappears.} printError := PrError; PrClose; {You do not want to report any printing errors until you have fallen } { through the printing loop. This will make sure that ALL of the Print } { Manager's open calls have their corresponding close calls, thereby } { enabling the Print Manager to close properly and that all temporary } { memory allocations are released.} IF (printError <> noErr) THEN DoError(ePrint, printError); SetPort(oldPort);END;Printing From the FinderTo print a document from the Finder, the user selects the document’s icon and chooses the Print command from the File menu. When the Print command is chosen, the Finder starts up the application and passes information to it indicating that the document is to be printed rather than opened on the screen. Your application should then do the following, preferably without going through its entire startup sequence: 1. Call the PrJobDialog function, described on page 1-43. If the user selected more than one document, you can use the PrJobMerge function, described on page 1-46, to apply the results of one job dialog box to all of the documents. 2. Print the document or documents. Most applications open the document on the screen while printing. Although this is not necessary, it is helpful to the user. You can also print from the Finder using the pDoc Apple event. See the chapter “Finder Interface” in the <italics\>Operating System volume of Inside Macintosh for more information about how to print from the Finder. Printing Each Page as a Separate DocumentSome applications use a method of printing that prints out each page of a spooled document as a separate print job in order to avoid running out of disk space while spooling the document to disk. You should not use this method, known as “spool a page, print a page,” because it only works for a printer directly connected to the user’s computer (and not to a network) and therefore creates device dependence, and because it’s extremely slow. If the printer is a remote or shared device (such as a LaserWriter printer or an ImageWriter printer connected by AppleTalk), another application could print a document between the pages of your user’s document. At worst, if both applications printing to the shared printer use the “spool a page, print a page” method, the printed documents could end up interleaved. The pages for one of the documents could be out of order, even when printed by itself. Printing From the Low-Level InterfaceThe low-level interface is the set of routines that use the Device Manager directly to print. Some printer drivers converts the routines in the low-level interface into their equivalents in the high-level interface, so you won’t gain a speed advantage by using the low-level routines. In fact, your code may run slower. The low-level interface is used primarily on the ImageWriter printer for printing text and graphics.If you want to use the low-level interface, you should use the code in Listing 1-2, so that the Printing Manager can properly convert the low-level calls to the high-level interface. Printing a page using the low-level interfacePrDrvrOpen; {opens the printer driver}PrCtlCall(iPrDevCtl, lPrDocOpen, 0, 0); {opens the document}PrCtlCall(iPrDevCtl, lPrPageOpen, 0, 0); {opens the page} {Here you send the data to be printed}PrCtlCall(iPrDevCtl, lPrPageClose, 0, 0); {closes the page}PrCtlCall(iPrDevCtl, lPrDocClose, 0, 0); {closes the document}PrDrvrClose; {closes the printer driver}The routines in the low-level interface are documented in “Low-Level Routines” on page 1-56 and “Low-Level Control Calls” on page 1-58. Checking for PrGeneralThe PrGeneral procedure (described on “Optimizing Printing” on page 1-51) allows you to determine the resolution of the printer, set the resolution you want, find out if the user has selected landscape printing, or force draft-quality printing. You call the PrGeneral procedure with one of five opcodes: GetRslDataOp, SetRslOp, GetRotnOp, DraftBitsOp, or NoDraftBitsOp. Four of these opcodes have data structures associated with them. (The fifth, NoDraftBitsOp, serves to reverse the effect of the DraftBitsOp opcode and so does not have its own data structure.) Not all printer drivers have implemented the PrGeneral procedure however, so your code can’t depend on being able to use it. Listing 1-3 shows how to check to see whether the current printer driver has implemented the PrGeneral procedure. In Listing 1-3, the current printing error is set to 0 or noErr. The opcode field of the page orientation record (type TGetRotnBlk) is set to the getRotnOp opcode, which is the opcode to determine if the user has chosen landscape orientation. The code passes the address of the page orientation record to the PrGeneral procedure. The code then calls PrErr to get any errors that result from calling PrGeneral. If the error is opNotImpl, the printer driver does support PrGeneral but not that particular opcode. If the error is resNotFound, the printer driver does not support PrGeneral. The code then sets the function result to FALSE. Checking for the PrGeneral procedureFUNCTION DoIsPrGeneralThere: Boolean;VAR getRotRec: TGetRotnBlk; myPrintErr: OsErr; BEGIN myPrintErr := 0; getRotRec.iOpCode := getRotnOp; getRotRec.hPrint := myPrRecHdl; PrGeneral(@getRotRec); myPrintErr := PrError; PrSetError(noErr); IF (myPrintErr = noErr) THEN DoIsPrGeneralThere := TRUE ELSE IF (myPrintErr = OpNotImpl) THEN { PrGeneral is supported but this opcode isn't. } DoIsPrGeneralThere := TRUE ELSE IF (myPrintErr = resNotFound) THEN { PrGeneral isn't supported by the current printer driver. } DoIsPrGeneralThere := FALSE;END;Determining the Resolution of the Current PrinterSome printer drivers support one of two possible kinds of resolution: discrete or variable. You can use the PrGeneral procedure (page 1-51) to determine the kind of resolution supported by the current printer and then use the highest resolution desired by the application or the user. Each printer has its own unique imaging capabilities. When you call PrGeneral with the value GetRslDataOp for the opcode field of the parameter block, the Printing Manager returns the resolutions that the printer supports. Figure 1-5 shows the get-resolution records (type TGetRslBlk) returned by the LaserWriter and ImageWriter printer drivers. Both contain all the fields of the TGetRslBlk data type, but the LaserWriter record has values for the X and Y resolution range fields and only one resolution record, whereas the ImageWriter record has a value of 0 in the X and Y resolution range fields and four resolution records. Resolutions for LaserWriter and ImageWriter printersYou can also set the imaging resolution you want to use. You call PrGeneral with the value SetRslOp for the opcode field of the parameter block and the resolutions in the X and Y directions you want to use via the set-resolution record (page 1-37). The Printing Manager returns the result code noErr if it has updated the print record with this new resolution, or noSuchRsl if the current printer doesn’t support this resolution.Listing 1-4 illustrates how to use the PrGeneral procedure to determine the possible resolutions for the current printer and then set the printer to the desired resolution.Using the GetRslDataOp and SetRslOp opcodes with PrGeneralFUNCTION DoSetMaxResolution (thePrRecHdl: THPrint): Integer;VAR maxDPI: Integer; resIndex: Integer; getResRec: TGetRslBlk; setResRec: TSetRslBlk;BEGIN maxDPI := 0; getResRec.iOpCode := getRslDataOp; PrGeneral(@getResRec); {At this point, we have an array of possible resolutions in the } { getResRec variable. After checking for errors, we loop through } { each resolution range record looking for the highest resolution } { available where x and y are equal. This loop makes no } { assumptions about the order of the resolution records.} IF (getResRec.iError = noErr) AND (PrError = noErr) THEN BEGIN FOR resIndex := 1 TO (getResRec.iRslRecCnt) DO BEGIN IF (getResRec.rgRslRec[resIndex].iXrsl = getResRec.rgRslRec[resIndex].iYrsl) AND (getResRec.rgRslRec[resIndex].iXrsl > maxDPI) THEN maxDPI := getResRec.rgRslRec[resIndex].iYrsl; END; {We now have the desired resolution, set it.} IF maxDPI <> 0 THEN BEGIN WITH setResRec DO BEGIN iOpCode := setRslOp; hPrint := thePrRecHdl; iXRsl := maxDPI; iYRsl := maxDPI; END; PrGeneral(@setResRec); END; IF (setResRec.iError = noErr) AND (PrError = noErr) AND (maxDPI <> 0) THEN DoSetMaxResolution := maxDPI; END ELSE DoSetMaxResolution := 0;END;You can reset the original resolutions used by the printer driver by calling the PrGeneral procedure with the SetRslOp opcode a second time. You should save the values contained in the iVRes and iHRes fields of the printer information record before making the first call to PrGeneral. You can also reset the original resolutions by calling the PrintDefault procedure with the print record, which sets all of the fields of the print record to the default values of the current printer resource file. However, if you use PrintDefault you lose all of the selections from the last time the user used the style dialog box. (You may want to set the original resolution because that may be the printer’s best resolution, though not its highest.)If, based on the information you get with a call to PrGeneral using the GetRslDataOp opcode, you decide to change the resolution with a call to PrGeneral using the SetRslOp opcode, the Printing Manager may need to change the appearance of the style and job dialog boxes, disabling some items. (The appearance of the dialog boxes and which items are disabled is up to the printer driver.) Therefore, you should determine and set the resolution before you present the Printing Manager dialog boxes to the user. Determining Page OrientationAt times it can be useful for your application to determine which page orientation the user selected in the style dialog box. For instance, if an image only fits on a page if it is printed in landscape orientation and the user has not selected landscape orientation, your application can remind the user to select this orientation before printing. Otherwise, the user gets a clipped image. If you call the PrGeneral procedure with the GetRotnOp opcode, the Printing Manager returns a handle to the current print record and a Boolean variable that says whether or not the user has selected landscape orientation. Because the user should have already selected the type of orientation when you check this value, you should not call PrGeneral with the GetRotnOp opcode until after you present the style dialog box to the user. Listing 1-5 illustrates how to determine whether the user has selected landscape orientation for the current document.Using the GetRotnOp opcode with the PrGeneral procedure to determine page orientationFUNCTION DoIsLandscapeModeSet (thePrRecHdl: THPrint): Boolean;VAR GetRotRec: TGetRotnBlk;BEGIN GetRotRec.iOpCode := getRotnOp; GetRotRec.hPrint := thePrRecHdl; PrGeneral(@getRotRec); IF (GetRotRec.iError = noErr) AND (PrError = noErr) AND GetRotRec.fLandscape THEN BEGIN DoIsLandscapeModeSet := TRUE; END ELSE DoIsLandscapeModeSet := FALSE;END;Choosing Draft-Quality PrintingIf your application needs to print only text or bitmaps, it can increase performance and save disk space by choosing draft-quality printing. The Printing Manager prints the document immediately, rather than spooling it to disk as with deferred printing. On the ImageWriter printer, draft printing produces quick, low-quality drafts. The LaserWriter printer does not print documents in draft-quality. In order to force draft-quality printing, you can call the PrGeneral procedure with the DraftBitsOp opcode. The DraftBitsOp opcode has no effect if the printer does not support draft-quality printing (like the LaserWriter printer) or does not support deferred printing.If you want to force draft-quality printing, you should call PrGeneral with the DraftBitsOp opcode before presenting the style and job dialog boxes to the user, particularly when the current printer is an ImageWriter printer. The use of the DraftBitsOp opcode disables the landscape icon in the style dialog box and the Best and Faster options in the job dialog box. Listing 1-6 illustrates how to force draft-quality printing.Using the DraftBitsOp opcode with the PrGeneral procedure to force draft quality printingFUNCTION DoDraftBits(thePrRecHdl: THPrint): Boolean;VAR draftBitsBlk: TDftBitsBlk;BEGIN draftBitsBlk.iOpCode := draftBitsOp; draftBitsBlk.hPrint := thePrRecHdl; PrGeneral(@draftBitsBlk); IF (draftBitsBlk.iError = noErr) AND (PrError = noErr) THEN DoDraftBits := TRUE { draft printing is on } ELSE DoDraftBits := FALSE; { draft printing is NOT on }END;You can call PrGeneral with the NoDraftBitsOp opcode to turn off the effects of the DraftBitsOp opcode, as shown in Listing 1-7. If you call PrGeneral with NoDraftBitsOp without first calling it with DraftBitsOp, the procedure does nothing. As with the DraftBitsOp opcode, you should call PrGeneral with the NoDraftBitsOp opcode before you present the style and job dialog boxes to the user. Using the NoDraftBitsOp opcode with the PrGeneral procedure to turn off draft quality printingFUNCTION DoNoDraftBits(thePrRecHdl: THPrint): Boolean;VAR draftBitsBlk: TDftBitsBlk;BEGIN draftBitsBlk.iOpCode := nodraftBitsOp; draftBitsBlk.hPrint := thePrRecHdl; PrGeneral(@draftBitsBlk); IF (draftBitsBlk.iError = noErr) AND (PrError = noErr) THEN DoNoDraftBits := TRUE { draft printing is NOT on } ELSE DoNoDraftBits := FALSE; { draft print is on }END;Altering the Style or Job Dialog BoxThe standard style and job dialog boxes that the printer resource file provides for the LaserWriter printer are shown on page 1-7. Each dialog box has options that the user can set. If you want to use the standard style or job dialog box, call the PrStlDialog function (page 1-43) or PrJobDialog (page 1-43) function . You may wish to add some additional options to these dialog boxes so that the user can customize the printing process even further. However, there are strict guidelines about altering style or job dialog boxes:n If you want to add items to the current dialog box, add them only at the end of the list. Do not delete items from the existing item list, rearrange them, or add new items in the middle of the list. n The additional options should be below the standard ones in the dialog box, leaving the standard ones unchanged. n Don’t count on an item retaining its current position on the screen or in the dialog item list in the code.n Don’t use more than half the smallest screen height for your items. Apple reserves the right to expand the items in the standard dialog boxes to fill the top half of the screen.n If you want to add a lot of items to the dialog boxes, be aware this may confuse users. You should consider having your own separate dialog box in addition to the existing Printing Manager dialog boxes. n Dialog boxes may actually be color windows, which may affect your code somewhat.If you want to modify either of the Printing Manager dialog boxes, you need to change the printing dialog box record (page 1-39). This record contains a pointer to the dialog box’s window, a pointer to the dialog event filter, and a pointer to procedures for evaluating dialog items, and a handle to the current print record. A dialog event filter is a function that extends the Dialog Manager’s event-handling functionality. When your application displays the style or job dialog box, you can use an event filter to handle events that the Dialog Manager doesn’t handle—such as update events in background applications or the Command-period key-down event. The dialog hook in the pItemProc field is analogous to the Standard File dialog hook: it tells you which item of which dialog box the user has selected, and you can handle the item or the printer driver can handle the item if it’s one of the original items of the dialog box. TPrDlg = RECORD Dlg: DialogRecord; {Ptr to the dialog box} pFltrProc: ModalFilterProcPtr; {The dialog event filter} pItemProc: PItemProcPtr; {The item evaluating proc.} hPrintUsr: THPrint; {The print record} fDoIt: Boolean; {Reserved by Apple} fDone: Boolean; {Reserved by Apple} lUser1: LongInt; {Reserved by Apple} lUser2: LongInt; {Reserved by Apple} lUser3: LongInt; {Reserved by Apple} lUser4: LongInt; {Reserved by Apple} END;If you want to customize a style or job dialog box, first call the initialization function for a pointer to that dialog box. The PrStlInit function (page 1-45) returns a handle to the standard style dialog box; the PrJobInit function (page 1-45) returns a handle to the standard job dialog box. Then you can call the PrDlgMain function (page 1-44) with the address of your own initialization function. The program DoModifyDialogs, given in Listing 1-8, modifies the job dialog box. The Print function calls the PrJobInit function and stores the handle to the job dialog box it returns in the variable PrtJobDialog. The Print function then calls the PrDlgMain function with the address of the program’s initialization function, MyJobDlgInit. The MyJobDlgInit function fills in the fields of the printing dialog box record, appends the customized dialog items onto the dialog box, replaces the original item handler with the customized item handler, and returns the modified job dialog box to the Print function. The customized dialog item handler is in the MyJobItems procedure. Note that your item handler must call the original item handler, so that the Printing Manager can handle original items in the dialog box.Please note that your dialog hook must call the standard dialog hook to handle all of the standard dialog’s original items. If you wish to have an event filter, handle it the same way that you do a dialog hook. The code in Listing 1-8 works for the style dialog box if you replace all of the functions specific to the job dialog box with those specific for the style dialog box.<36pt\>\x12 <8bat\>uAdding items to a job dialog boxSee the chapter “Dialog Manager” in the Inside Macintosh: <italics\>Macintosh Toolbox for more information about dialog boxes, dialog items, and filter procedures. See the chapter “Standard File Package” in the Inside Macintosh: <italics\>Operating System volume for more information about the Standard File dialog hook. Writing an Idle ProcedureThe Printing Manager runs the idle procedure while it sends a document to the printer. (See “The Idle Procedure” on page 1-8.) The Printing Manager’s default idle procedure allows the user to cancel printing. The procedure just polls the keyboard and sets a Printing Manager error code if the user types Command-period (to cancel the printing job). If you use the default procedure, you should display a dialog box during printing to inform the user that the Command-period command is available.If you choose to write your own idle procedure instead of using the default Printing Manager procedure, there are several guidelines you must follow:n If you designate an idle procedure, you must set the PIdleProc field of the print record after presenting the dialog boxes, validating the print record, and initializing the fields in the printing record, because the routines that perform these operations reset the PIdleProc field to NIL. n You must install your idle procedure in the print record before calling the PrOpenDoc procedure. Otherwise, the printer driver does not give the idle procedure any time. You install a pointer to your procedure in the pIdleProc field of the printing job subrecord (page 1-31). n Do not attempt any printing from within the idle procedure, because the Printing Manager is not reentrant.n You must call WaitNextEvent to capture mouse clicks or the Command-period sequence that signals the user wants to cancel printing.n Don’t call the QuickDraw OpenPicture function or DrawPicture procedure. n You must save the printer’s grafPort upon entry to the idle procedure and restore it upon exit if you draw anything within the idle procedure. If you don’t, the printer driver draws into the grafPort of your dialog box instead of its own grafPort. To save the printer’s grafPort, call the GetPort procedure when entering the idle procedure. Before you exit, call the SetPort procedure to set the port back to the printer driver’s grafPort. (The GetPort and SetPort procedures are described in the chapter “QuickDraw”.)n If your idle procedure changes the resource chain, you should save the printer driver’s resource chain by calling the CurResFile function and saving the ID of the printer driver’s resource file at the beginning of your idle procedure. (Any routine that changes the value of the global variable TopMapHdl, such as the OpenResFile function or the UseResFile procedure, changes the resource chain. Some printer drivers assume the resource chain does not change, and you may get an error if you do change it.) When you exit for from the idle procedure, restore the resource chain with the UseResFile procedure. If you are not changing the resource chain, you do not need to save the resource chain. (CurResFile, OpenResFile, and UseResFile are described in the chapter “Resource Manager” of Inside Macintosh: <italics\>Operating System.)n Avoid calling the PrError function within the idle procedure. Errors that occur while it is executing are usually temporary and serve only as internal flags for communication within the printer driver, not for the application. If you absolutely must call PrError within your idle procedure and an error occurs, do not cancel printing. Wait until the last called printing procedure returns and then check to see if the error still remains. For information about installing a procedure to handle requests to cancel printing or pause printing, see “Canceling or Pausing the Printing Process” on page 1-28. Optimizing PrintingQuickDraw is the primary means you use in order to print, and in general you can use QuickDraw in the printing grafPort exactly as you would for a screen grafPort. There are a few things to note when drawing to the printing grafPort: n With each new page, you get a completely reinitialized grafPort, so you’ll need to reset font information and other grafPort characteristics as desired.n Don’t make calls that don’t do anything on the printer. For example, erase operations are quite time-consuming and normally aren’t needed on the printer.n Don’t use clipping to select text to be printed. There are a number of subtle differences between how text appears on the screen and how it appears on the printer; you can’t count on knowing the exact dimensions of the rectangle occupied by the text.n Don’t use fixed-width fonts to align columns. Since spacing gets adjusted on the printer, you should explicitly move the pen to where you want it.n Don’t use the Outline text style to create white text on a black background.n Avoid using the QuickDraw erase calls (for example, EraseRect). An erase routine takes time because every bit (90,000 bits per square inch) has to be cleared. Erasing is unnecessary because the paper does not need to be erased the way the screen does. Avoid using the TextBox procedure, which makes calls to the EraseRect procedure. You might want to use a different method of displaying text (for example, DrawString or DrawText) or write your own version of TextBox.n Avoid changing fonts frequently. n Because of the way rectangle intersections are determined, if your clip region falls outside of the rectangle given by the rPage field of the printer information subrecord of the print record, you slow down the printer substantially.Optimizing PostScript PrintingWhile your printing code should be device-independent, you can optimize it for a LaserWriter printer that uses PostScript. (You cannot be sure that the current printer is a PostScript printer, so you may need to send down two or more versions of the same file: one for a PostScript printer, one for a QuickDraw printer.) For printing to a PostScript printer, you’ll need to observe the following limitations: n Regions aren’t supported; try to simulate them with polygons or bitmaps. n Clipping regions should be limited to rectangles. PostScript clips non-square patterns to squares. n The invert data type, part of the QuickDraw grafverb data type, is not supported by the PostScript LaserWriter printer driver. n Transfer modes are ignored for all QuickDraw objects except 1-bit bitmaps. With 1-bit bitmaps, srcCopy, srcOr, srcBic, notSrcCopy, and notSrcBit are drawn. The copy transfer mode is the only transfer mode supported for all objects except text and bit images. n There can be a small difference in glyph widths between fonts rendered on the screen and on the printer. Only the endpoints of text strings are the same. n PostScript does not support color patterns that use colors other than red, green, blue, cyan, yellow, magenta, white, and black. n The printer may print some large patterns at half or smaller sizes, depending on its resolution. n Polygons and smoothed polygons that result in the creation of paths larger than the limit of the PostScript printer (typically 1500 or 3000, depending on the version of PostScript) result in a PostScript error.Although the LaserWriter is relatively fast, there are some techniques an application can use to ensure its maximum performance.n Printing patterns takes time, because the bitmap for the pattern has to be built. The patterns black, white, and some of the gray patterns have been optimized to use the PostScript gray scales. Remember that when your application sends a document to the LaserWriter printer, it must use immediate printing and cannot use deferred printing; your print code, the document’s data, and the printer driver have to be in memory simultaneously. In order to ensure that you have enough memory available to load the LaserWriter printer driver’s code, you should have all the code you need for printing in a separate segment and unload everything else. For information on offscreen bitmaps, the grafverb data type, transfer modes, and the routines mentioned here, see the chapter “QuickDraw”. For more information on PostScript, see the PostScript Language Reference Manual, available from Addison-Wesley. Providing Names of Documents Being PrintedSome printers (usually those that are shared between many users, like the LaserWriter printer) can provide the names of the users who are printing and the documents that are being printed to others interested in using the printer. Providing the names of users and documents is a courtesy to other users on the network. The Printing Manager gets the name of the document being printed from the title on the frontmost window on the user’s screen. The PrOpenDoc and PrValidate procedures call the FrontWindow procedure to get the document’s name. The Printing Manager can’t get a document name if your application doesn’t display windows while printing. For example, many applications do not open windows for their documents when the user prints from the Finder. If there is no front window, or if the window’s title is empty, the Printing Manager defaults to “Unspecified.”You can ensure that the document name is available by putting up a window containing a message like “Press Command–period to cancel printing,” and give it the document’s title. If the window is one that doesn’t have a title bar (like those of type dBoxProc), this title is not displayed. If you don’t want to put up a visible window, you can create a tiny window (for instance, type plainDBox) and hide it behind the menu bar by giving it the global coordinates of (1,1,2,2). See the chapter “The Window Manager” in Inside Macintosh: <italics\>Macintosh Toolbox for information about dBoxProc and plainDBox window types. Do not set the document name in the print record directly. Not all printer drivers support this field, and Apple does not guarantee that internal fields of the Printing Manager’s data structures will remain the same.<36pt\>\x12 <8bat\>u Canceling or Pausing the Printing ProcessIf you install a procedure for handling requests to cancel printing, do not include an option to pause the printing process. Pausing may cause timeout problems when printing to the LaserWriter printer. Communication between the Macintosh computer and the LaserWriter must be maintained to prevent a job or a wait timeout. If there is no communication for a period of time (over two minutes), the printer times out and the print job terminates due to a wait timeout. Because there is no good way to determine the type of printer, you should be aware of the possibility of a LaserWriter printer timing out for a user who wants to pause printing for over two minutes. Handling Printing ErrorsYou should always check for error conditions while printing by calling the PrError function. Errors returned may include AppleTalk and Operating System errors in addition to Printing Manager errors.Don’t call PrError from within your idle procedure. See “Writing an Idle Procedure” on page 1-25 for more information. If you determine that an error has occurred after the completion of a printing routine, stop printing. Call the close routine that matches any open routine you have called. For example, if you call PrOpenDoc and received an error, skip to the next PrCloseDoc; if you called PrOpenPage and got an error, skip to the next PrClosePage and PrCloseDoc. Remember that if you have called some open procedure, you must call the corresponding closing procedure to ensure that the printer driver closes properly and that all temporary memory allocations are released and returned to the heap. Using Alert or Dialog Boxes to Report ErrorsDo not display any alert or dialog boxes to report an error until the end of the printing loop. Once at the end, check for the error again; if there is no error assume that printing completed normally. If the error is still present, then you can alert the user. This technique is important for two reasons. First of all, if you display a dialog box in the middle of the printing loop, it could cause errors that can terminate an otherwise normal job. For example, if the printer is an AppleTalk printer, the connection can be terminated abnormally since the driver would be unable to respond to AppleTalk requests received from the printer while the dialog box was waiting for input from the user. If the printer does not hear from the Macintosh system within a short period of time (anywhere from 30 seconds to 2 minutes, depending on the driver), it assumes that the Macintosh system is no longer there and times out. The timeout results in a prematurely broken connection, causing another error, to which the application must respond. (See “Canceling or Pausing the Printing Process” on page 1-28.)The second reason is that the driver may have already displayed its own dialog box in response to an error. In this instance, the driver posts an error to let the application know that something went wrong and it should cancel printing. For example, when the LaserWriter driver detects that the Laser Prep version that has been downloaded to the LaserWriter is different from that with which the user is trying to print, it displays the appropriate dialog box informing the user of the situation and giving the user the option of reinitializing the printer. If the user chooses to cancel printing, the driver posts an error to let the application know that it needs to cancel printing, but since the driver has already taken care of the error by displaying a dialog box, the error is reset to 0 before the printing loop is complete. The application should check for the error again at the end of the printing loop, and if it still indicates an error, the application can then display the appropriate dialog box.Interpreting PrGeneral ErrorsIf you are using the PrGeneral procedure, be prepared to receive the following errors: noSuchRsl, opNotImpl, and resNotFound. In all three cases, the application should be prepared to continue to print without using the features of that particular opcode.The resNotFound error means the current printer driver does not support the PrGeneral procedure. This lack of support should not be a problem for your application, but you need to be prepared to deal with this error. If you receive a resNotFound result code from PrError, clear the error with a call to PrSetError with a value of 0 as the parameter; otherwise, PrError might still contain this error the next time you check it, which would prevent your application from printing.ReferenceThis section describes the data structures, routines, and resources provided by the Printing Manager. The “Data Structures” section shows the Pascal data structures used by the Printing Manager. The “Routines” section describes the routines you can use to print a document, produce or alter a printing dialog box, and handle printing errors. Data StructuresThe data structures of the Printing Manager primarily fall into two groups: the records and subrecords of the print record, and the records used by the PrGeneral procedure. In almost all cases, a field in one of the Printing Manager data structures that is listed as being reserved contains device-dependent information. You should not rely on this information being available or accurate when printing from your application. TPrint The TPrint record is the print record that every document must have before you can print it. It contains handles to the print information and job subrecords (TPrInfo, described on page 1-31 and TPrJob, described on page 1-31). TPrint = RECORD iPrVersion: Integer; { Printing software version} prInfo: TPrInfo; { the PrInfo data associated with the current style.} rPaper: Rect; { The paper rectangle [offset from rPage]} prStl: TPrStl; { This print request's style.} prInfoPT: TPrInfo; { Reserved } prXInfo: TPrXInfo; { Print-time (expanded) Print info record.} prJob: TPrJob; { The Print Job request Total of the above; 120-82 = 38 bytes needed to fill 120} printX: ARRAY [1..19] OF Integer; {Spare to fill to 120 bytes!} END;iPrVersion The version of the Printing Manager that initialized this print record. It is recommended that you use the PrDrvrVers function (page 1-58) instead if you want to determine the current version of the printer driver; your application may not have updated this print record for the current printer. prInfo The information needed for page composition. This record is of type TPrInfo, which is described on page 1-31.rPaper The paper rectangle. This rectangle encompasses the page rectangle, which is specified by the rPage field of the printer information record, described on page 1-31.prStl The printer’s device number and the feed type, described on page 1-33.prInfoPT Reserved by Apple. prXInfo Reserved by Apple. prJob Information about this particular printing job. The results of the job dialog box sets its contents. This record is of type TPrJob, which is described on page 1-31. printX Reserved by Apple.If you try to use a print record that’s invalid for the current version of the Printing Manager or for the currently installed printer, the Printing Manager will correct the record by filling it with default values. You should not alter the contents of the print record directly. TPrInfo The TPrInfo record is the printer information subrecord of the print record. It contains the vertical and horizontal resolutions of the printer and coordinates of the page rectangle. TPrInfo = RECORD iDev: Integer; {Font mgr/QuickDraw device code} iVRes: Integer; {Resolution of device, in device coordinates} iHRes: Integer; {..note: V before H => compatable with Point.} rPage: Rect; {The page (printable) rectangle in device coordinates.} END;iDev Reserved by Apple.iVRes The printer’s vertical resolution in dots per inch. The default value is 72, unless you have made a call to the PrGeneral procedure with the SetRsl opcode (described in “Determining the Resolution of the Current Printer” on page 1-17). iHRes The printer’s horizontal resolution in dots per inch. The default value is 72, unless you have made a call to the PrGeneral procedure with the SetRslOp opcode. rPage The page rectangle. This rectangle is inside the paper rectangle, specified by the rPaper field of the print record, described on page 1-30. The style dialog box sets this value. TPrJob The TPrJob subrecord of the TPrint print record contains information about a particular printing job. The user accepting the contents of the job dialog box or your application calling the PrintDefault procedure (page 1-42) sets its contents.TPrJob = RECORD iFstPage: Integer; {Page Range.} iLstPage: Integer; iCopies: Integer; {Number of copies.} bJDocLoop: SignedByte; {The Doc style: Draft or Spool} fFromUsr: Boolean; {Reserved} pIdleProc: PrIdleProcPtr; {Pointer to the background procedure} pFileName: StringPtr; {Spool File Name: NIL for default.} iFileVol: Integer; {Spool File vol, set to 0 initially} bFileVers: SignedByte; {Spool File version, set to 0 initially} bJobX: SignedByte; {Reserved} END;iFstPage The page number of the first page being printed.iLstPage The page number of the last page being printed. iCopies The number of copies requested, which is also the number of times your application should send the document to the printer. However, some printer drivers handle multiple copies internally and this value will be 1.bJDocLoop The printing method that the Printing Manager will use. It will be one of the following predefined constants: CONST bDraftLoop = 0; {draft printing} bSpoolLoop = 1; {spool printing}fFromUsr Reserved by Apple.pIdleProc A pointer to the background procedure (described in “The Idle Procedure” on page 1-8) for this printing operation. pFileName The name of the spool file. This field is initialized to NIL and is should not be changed by your application. This field denotes the default file name (normally 'Print File') stored in the printer resource file.iFileVol The volume reference number of the spool file. This field is initialized to 0, representing the default volume. You can use the File Manager function SetVol (described in the File Manager chapter of the <italics\>Operating System volume) to change the default volume. bFileVers The version number of the spool file, initialized to 0. bJobX Reserved by Apple.TPrStl The TPrStl record contains the device number of the current printer and the feed type currently selected (paper cassette or manual). All other fields are reserved. TPrStl = RECORD wDev: Integer; iPageV: Integer; iPageH: Integer; bPort: SignedByte; feed: TFeed; END;wDev The high-order byte contains the device number of the current printer. The low-order byte is reserved.iPageV Reserved by Apple.iPageH Reserved by Apple.bPort Reserved by Apple.feed The feed type currently selected. The possible values are: TFeed = (feedCut,feedFanfold,feedMechCut,feedOther);TPrStatus The TPrStatus record is used by the PrPicFile procedure (page 1-50), which you use to print spooled documents. TPrStatus = RECORD iTotPages: Integer; {Total pages in Print File.} iCurPage: Integer; {Current page number} iTotCopies: Integer; {Total copies requested} iCurCopy: Integer; {Current copy number} iTotBands: Integer; {Reserved} iCurBand: Integer; {Reserved} fPgDirty: Boolean; {True if current page has been written to.} fImaging: Boolean; {Reserved} hPrint: THPrint; {Handle to the active print record} pPrPort: TPPrPort; {Ptr to the active PrPort} hPic: PicHandle; {Handle to the active Picture} END;iTotPages The total number of pages being printed. This is the same value as the value of iLastPage minus the value of iFirstPage, which are both from the TPrJob record. iCurPage The sequence number of the page currently being printed. For example, if the user prints pages 10 through 15 of a 20-page document, the value of the iCurPage field for page 10 is 1. iTotCopies The total number of copies requested. This value may be different from the value of the field iCopies from TPrJob. iCurCopy The number of the current copy being printed. iTotBands Reserved by Apple. iCurBand Reserved by Apple. fPgDirty A flag indicating whether the printer has begun printing the current page. Set to TRUE if there has been any imaging on the current page.fImaging A flag indicating whether the printer driver is in the middle of a DrawPicture call. hPrint The handle to the current print record.pPrPort The pointer to the active printing grafPort data type.hPic The handle to the active picture. This is used by the printer driver; your application should not alter it. TPrPortThe TPrPort record is the printing grafPort, which contains a handle to a QuickDraw grafPort, among other fields. TPrPort = RECORD gPort: GrafPort; {The Printer's grafPort.} gProcs: QDProcs; {The procedures for printing in the grafPort} lGParam1:LongInt; {Reserved} lGParam2:LongInt; {Reserved} lGParam3:LongInt; {Reserved} lGParam4:LongInt; {Reserved} fOurPtr:Boolean; {Reserved} fOurBits:Boolean; {Reserved}END;gPort The Printer’s grafPort.gProcs Pointers to routines that the printer driver may have designated to take the place of QuickDraw routines. See the chapter “QuickDraw” for more information. You can include a pointer to routines that you would like to include in the grafProcs field of the grafPort data type. lGParam1 Reserved by Apple. lGParam1 Reserved by Apple. lGParam1 Reserved by Apple. lGParam1 Reserved by Apple. fOurPtr Reserved by Apple. fOurBits Reserved by Apple. TGnlData The TGnlData record is the basic record used by the PrGeneral procedure. Although no opcode of PrGeneral uses TGnlData, all other records that are used are based on this record. TGnlData = RECORD iOpCode: Integer; iError: Integer; lReserved: LongInt; {more fields here depending on call} END;iOpCode The opcode that is passed to PrGeneral to obtain the requested feature. There are five possible opcodes: GetRslDataOp, SetRslOp, GetRotnOp, DraftBitsOp, and NoDraftBitsOp. iError The result code returned by PrGeneral.lReserved Reserved by Apple. Additional fields may follow this field, depending on the opcode used. See the descriptions of the TGetRslBlk (page 1-35), TSetRslBlk (page 1-37), TDftBitsBlk (page 1-38), and TGetRotnBlk (page 1-38) records. TGetRslBlk The TGetRslBlk data structure is the record that you pass to the PrGeneral procedure when you use the GetRslDataOp opcode. The PrGeneral procedure returns the record with the resolutions available on the current printing device. For information on how to use the GetRslDataOp opcode with the PrGeneral procedure, see “Determining the Resolution of the Current Printer” on page 1-17. If the printer uses discrete printing, the number of resolution values available on the printer is listed in the iRslRecCnt field and the records containing those values are in the rgRslRec array. If the printer supports variable printing, the resolution ranges in the X and Y directions are in the xRslRg and yRslRg fields. TGetRslBlk = RECORD iOpCode: Integer; {The opcode passed to PrGeneral} iError: Integer; {The result code returned by PrGeneral} lReserved: LongInt; {Reserved by Apple} iRgType: Integer; {The printer driver version number} xRslRg: TRslRg; {The X-direction resolution range} yRslRg: TRslRg; {The Y-direction resolution range} iRslRecCnt: Integer; {The number of resolution records} rgRslRec: ARRAY [1..27] OF TRslRec; {The array of resolution records} END;iOpCode The opcode passed to the PrGeneral procedure to obtain the requested feature. In the case of the TGetRslBlk record, the opcode is GetRslDataOp. iError The result code returned by PrGeneral.lReserved Reserved by Apple. iRgType The version number returned by the printer driver. The LaserWriter and ImageWriter printers always return 1. If this field is not 1, don’t use the data in this record. xRslRg The resolution range supported for the X direction. If the current printer does not support variable resolution, this value is 0. yRslRg The resolution range supported for the Y direction. If the current printer does not support variable resolution, this value is 0. iRslRecCnt The number of resolution records used by a particular printer driver, up to 27.rgRslRec An array of resolution records, each specifying a discrete resolution at which the current printer can print an image. The xRslRg and yRslRg fields of the TGetRslBlk record are of type TRslRg. This data structure contains the minimum and maximum resolutions supported by the current printer driver. If the current printer does not support variable resolution, both fields of this subrecord are 0.TRslRg = RECORD iMin: Integer; {The minimum resolution supported} iMax: Integer; {The maximum resolution supported} END;iMin The minimum resolution supported by the current printer. If the printer supports only discrete resolutions, this value is 0.iMax The maximum resolution supported by the current printer. If the printer supports only discrete resolutions, this value is 0.The rgRslRec field of the TGetRslBlk record are of type TRslRec. The TRslRec subrecord specifies a discrete resolution supported by the printer. A printer driver can have up to 27 separate TRslRec records. (The ImageWriter printer driver contains 4 such records.)TRslRec = RECORD iXRsl: Integer; {Discrete resolution, X-direction} iYRsl: Integer; {Discrete resolution, Y-direction} END;iXRsl The discrete resolution supported in the X direction. iYRsl The discrete resolution supported in the Y direction. TSetRslBlk The TSetRslBlk data structure is the record that you pass to the PrGeneral procedure when you use the SetRslOp opcode. It contains the resolutions that you want to use on the current printing device. For information on how to use the SetRslOp opcode with the PrGeneral procedure, see “Determining the Resolution of the Current Printer” on page 1-17. TSetRslBlk = RECORD iOpCode: Integer; {The opcode passed to PrGeneral} iError: Integer; {The result code returned by PrGeneral} lReserved: LongInt; {Reserved by Apple} hPrint: THPrint; {A handle to current print record} iXRsl: Integer; {The X-direction resolution you want} iYRsl: Integer; {The Y-direction resolution you want} END;iOpCode The opcode passed to PrGeneral to obtain the requested feature. In the case of the TSetRslBlk record, the opcode is SetRslOp. iError The result code returned by PrGeneral.lReserved Reserved by Apple. hPrint A handle to the print record. Your application should have already created this print record and passed it through the PrintDefault procedure to make sure that all of the information in the handle is good. iXRsl The resolution in the X direction that you want the printer to use when printing. iYRsl The resolution in the Y direction that you want the printer to use when printing. If the iError field returns noErr, the Printing Manager updates the print record with this resolution, which the printer uses at print time. If the iError field returns noSuchRsl, the current printer doesn’t support the requested resolution and the printer driver does not change the setting. TDftBitsBlk The TDftBitsBlk record is the data structure is the record that you pass to the PrGeneral procedure when you use the DraftBitsOp opcode. For information on how to use the DraftBitsOp opcode with the PrGeneral procedure, see “Choosing Draft-Quality Printing” on page 1-21. TDftBitsBlk = RECORD iOpCode: Integer; {The opcode passed to PrGeneral} iError: Integer; {The result code returned by PrGeneral} lReserved: LongInt; {Reserved by Apple} hPrint: THPrint; {A handle to current print record} END;iOpCode The opcode passed to the PrGeneral procedure to obtain the requested feature. In the case of the TDftBitsBlk record, the opcode is DraftBitsOp. iError The result code returned by the PrGeneral procedure.lReserved Reserved by Apple. hPrint A handle to the print record. Your application should have already created this print record and passed it through the PrintDefault procedure to make sure that all of the information in the handle is good. TGetRotnBlk The TGetRotnBlk record is the data structure is the record that you pass to the PrGeneral procedure when you use the GetRotnOp opcode. PrGeneral returns it with a Boolean variable that tells you whether the user has selected landscape orientation. For information on how to use the GetRotnOp opcode with the PrGeneral procedure, see “Determining Page Orientation” on page 1-20. TGetRotnBlk = RECORD iOpCode: Integer; {The opcode passed to PrGeneral} iError: Integer; {The result code returned by PrGeneral} lReserved: LongInt; {Reserved by Apple} hPrint: THPrint; {A handle to current print record} fLandscape: Boolean; {If the user wants landscape printing} bXtra: SignedByte; {Reserved by Apple} END;iOpCode The opcode passed to the PrGeneral procedure to obtain the requested feature. In the case of the TGetRotnBlk record, the opcode is GetRotnOp. iError The result code returned by the PrGeneral procedure.lReserved Reserved by Apple. hPrint A handle to the print record. Your application should have already created this print record and passed it through the PrintDefault procedure to make sure that all of the information in the handle is good. fLandscape A Boolean variable that determines whether the user has selected landscape orientation in the style dialog box. A value of TRUE indicates the user has selected landscape orientation.bXtra Reserved by Apple. TPrDlg The TPrDlg record contains the information needed to set up either the style or job dialog box. The PrStlInit and PrJobInit function return this record, set up for the style and job dialog boxes respectively. You can find information on how to customize a printing dialog box in “Altering the Style or Job Dialog Box” on page 1-23. TPrDlg = RECORD Dlg: DialogRecord; {Ptr to the dialog box} pFltrProc: ModalFilterProcPtr; {The dialog event filter} pItemProc: PItemProcPtr; {The Item evaluating proc.} hPrintUsr: THPrint; {The print record} fDoIt: Boolean; {Dialog box confirmed} fDone: Boolean; {User’s interaction completed} lUser1: LongInt; {Storage for your application} lUser2: LongInt; {Storage for your application} lUser3: LongInt; {Storage for your application} lUser4: LongInt; {Storage for your application} END;Dlg A pointer to the dialog box, which may be either the style or job dialog box. pFltrProc A pointer to the dialog event filter. pItemProc A pointer to the routine that handles the items of the dialog box, also known as the dialog hook. hPrintUsr The document’s print record.fDoIt Whether the user has confirmed the dialog box. TRUE means the user has confirmed it by clicking “OK”.fDone Whether the user’s interaction is completed. TRUE means the user has clicked either “OK” or “Cancel”. lUser1 In this field and the following fields, your application can store any kind of data you wish for the dialog box, such as global storage. lUser2 See lUser1.lUser3 See lUser1.lUser4 See lUser1.RoutinesThis section describes the routines you use to initialize the Printing Manager, print a document, produce or alter a style or job dialog box, and handle printing errors.The trap macro for all of the routines in the Printing Manager is _PrGlue, and the trap is $A8FD. The routine selector for each individual routine is provided with the routine. Opening and Closing the Printing Manager You must always open the Printing Manager before attempting to print and close it when printing is finished. If you don’t, you risk crashing the user’s system. 1PrOpen Use the PrOpen procedure to prepare the Printing Manager for use. PROCEDURE PrOpen;DESCRIPTIONYou must always use the PrOpen procedure before attempting to print anything. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrOpen procedure is $C8000000. Trap macro Trap_PrGlue $A8FD1PrClose Use the PrClose procedure to close the Printing Manager and release the memory it used. PROCEDURE PrClose;DESCRIPTIONThe PrClose procedure is the call that balances a call to the PrOpen procedure.If you have opened the Printing Manager with the PrOpen procedure, do not call the PrDrvrClose procedure to close the Printing Manager.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrClose procedure is $D0000000. Trap macro Trap_PrGlue $A8FDFilling and Verifying Print RecordsYou must fill the print record with the values for the current printer driver or, if a print record already exists, verify that the information in the print record is correct. If the print record is not valid for the current printer driver, the document will not print. The PrValidate function ensures that the print record is compatible with the current versions of the printer driver. The PrintDefault procedure fills in a print record with the default values for the currently selected printer. These functions may change the coordinates of the page rectangle or any other value in the print record; you should not assume any values will remain the same.1PrValidate When you have a print record, whether an existing one from the current document or a new one you have just created, you can use the PrValidate function to check the contents of the specified print record for compatibility with the current version of the printer driver of the current printer. FUNCTION PrValidate (hPrint: THPrint): Boolean;hPrint The handle to the specified print record, which may be a new record or an existing one from a document.DESCRIPTIONIf the print record is valid, PrValidate returns FALSE, meaning there is no change. If the record is invalid, the function returns TRUE and the Printing Manager adjusts the record with the default values stored in the printer resource file.PrValidate also makes sure that all the information in the print record is internally self-consistent and updates the print record as necessary. These changes do not affect the function’s Boolean result. If you have just created a print record, using the PrintDefault procedure, you do not need to call PrValidate. The PrintDefault procedure does this automatically. You should never call PrValidate between the pages of a document. This restriction holds as well for the PrStlDialog and PrJobDialog functions and the PrintDefault procedure, which call PrValidate.<36pt\>\x12 <8bat\>sASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrValidate function is $52040498. Trap macro Trap_PrGlue $A8FD1PrintDefault When you create a print record, you use the PrintDefault procedure to fill the fields of the specified print record with default values for resolution, number of copies, and other information in the print record and its subrecords. PROCEDURE PrintDefault (hPrint: THPrint);hPrint The handle to the specified print record, which may be a new record or an existing one from a document.DESCRIPTIONThe default values for the current printer are stored in the printer resource file. PrintDefault puts these values in the print record, erasing the ones that may already be there (if the print record already existed). PrintDefault calls PrValidate to check the print record for compatibility with the current version of the printer driver. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrintDefault procedure is $20040480. Trap macro Trap_PrGlue $A8FDSEE ALSOThe print record is discussed in “The Print Record and the Printing Loop” on page 1-7. Displaying and Customizing the Printing Dialog BoxesThe style and job dialog boxes allow the user to tell your application how to print the document: page orientation, number of copies, page range to print, and so on. You can use the dialog boxes provided by the Printing Manager, or you can customize the standard dialog boxes. You can copy the results of one job dialog box to several documents when the user wants to print several documents at once.The PrStlDialog and PrJobDialog functions display the standard style and job dialog boxes. The PrDlgMain function, using the PrStlInit and PrJobInit functions, allows you to customize the standard style and job dialog boxes for your application. The PrJobMerge procedure allows you to use one job dialog box for several print jobs, such as when the user prints several documents from the Finder. 1PrStlDialog Call the PrStlDialog function displays a style dialog box, which the user can use to specify the page dimensions and other information needed for a page setup. FUNCTION PrStlDialog (hPrint: THPrint): Boolean;hPrint The handle to the specified print record, which may be a new record or an existing one from a document.DESCRIPTIONThe Printing Manager takes the initial settings displayed in the style dialog box from the print record. If the user confirms the dialog box, the PrStlDialog function returns TRUE, and the Printing Manager saves the results of the dialog box in the specified print record and calls the PrValidate function. Otherwise, the print record is left unchanged and the function returns FALSE. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrStlDialog function is $2A040484. Trap macro Trap_PrGlue $A8FD1PrJobDialog You can call the PrJobDialog function to produce a job dialog box, which the user can use to determine the print quality, the range of pages to print, and so on. FUNCTION PrJobDialog(hPrint: THPrint): Boolean;hPrint The handle to the specified print record, which may be a new record or an existing one from a document.DESCRIPTIONThe printer driver shows the default settings for the current printer in the job dialog box. If the user confirms the dialog box, the Printing Manager updates both the print record and the printer resource file and calls the PrValidate function, and the PrJobDialog function returns TRUE. Otherwise, the print record and the printer resource file are left unchanged and the function returns FALSE. If the PrJobDialog function returns TRUE, you should proceed with the requested printing operation. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrJobDialog function is $32040488. Trap macro Trap_PrGlue $A8FD1PrDlgMain Use the PrDlgMain function to display a style or job dialog box after you have customized it. FUNCTION PrDlgMain (hPrint: THPrint; pDlgInit: PDlgInitProcPtr): Boolean;hPrint The handle to the specified print record, which may be a new record or an existing one from a document.pDlgInit A pointer to an initialization procedure for one of the two Printing Manager printing dialog boxes, or to your own initialization procedure. DESCRIPTIONYou can use the PrDlgMain function to set up a printing dialog box, or you can initalize the style or job dialog box yourself and then send PrDlgMain your initialization function. The printing dialog boxes initialization functions, PrStlInit and PrJobInit, set up the dialog box in a TPrDlg record (described on page 1-39), which contains pointers for the dialog event filter and the procedure for evaluating the items of the dialog box, including your own. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrDlgMain function is $4A040894. Trap macro Trap_PrGlue $A8FDSEE ALSOFor more information about customizing style or job dialog boxes, see “Altering the Style or Job Dialog Box” on page 1-23.1PrStlInit The PrStlInit function returns a pointer to the style dialog box (described on page 1-7) in memory but does not display the dialog box.FUNCTION PrStlInit (hPrint: THPrint): TPPrDlg;hPrint The handle to the specified print record, which may be a new record or an existing one from a document.DESCRIPTIONYou pass the address of the PrStlInit function in the pDlgInit parameter of the PrDlgMain function, which is described on page 1-44. The PrStlInit function returns a pointer to a printing style dialog box.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrStlInit function is $3C04040C. Trap macro Trap_PrGlue $A8FDSEE ALSOFor more information about customizing style or job dialog boxes, see “Altering the Style or Job Dialog Box” on page 1-23.1PrJobInit The PrJobInit function returns a pointer to the job dialog box (described on page 1-7) in memory but does not display the dialog box. FUNCTION PrJobInit (hPrint: THPrint): TPPrDlg;hPrint The handle to the specified print record, which may be a new record or an existing one from a document.DESCRIPTIONYou pass the address of the PrJobInit function in the pDlgInit parameter of the PrDlgMain function, which is described on page 1-44. The PrJobInit function returns a pointer to a printing job dialog box.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrJobInit function is $44040410. Trap macro Trap_PrGlue $A8FDSEE ALSOFor more information about customizing style or job dialog boxes, see “Altering the Style or Job Dialog Box” on page 1-23.1PrJobMerge You can use the PrJobMerge procedure to display a job dialog box just once and then copy the job information to several print records, which means that you can print several documents with one dialog box. This is useful when the user prints from the Finder. PROCEDURE PrJobMerge (hPrintSrc: THPrint;hPrintDst: THPrint); hPrintSrc The print record from the Finder.hPrintDst The print record from the document. DESCRIPTIONThe PrJobMerge procedure first calls the PrValidate function for each of the print records named by the hPrintSrc and hPrintDst parameters. It then copies all of the information set as a result of a job dialog box from the hPrintSrc parameter to the hPrintDst parameter while preserving the values set by the style dialog box for that print record (for instance, landscape orientation). Finally, the PrJobMerge procedure makes sure that all the fields of the print record named by the hPrintDst parameter are internally self-consistent. You must call PrJobMerge for each document the user wants to print; however, it can only make one copy of each document. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrJobMerge procedure is $5804089C. Trap macro Trap_PrGlue $A8FDPrintingIn addition to opening and closing the Printing Manager, you must open and close the document being printed and each page of the document before you can print it. The PrOpenDoc function and PrCloseDoc procedures open and close the document, and the PrOpenPage and PrClosePage procedures open and close the current page.You must use the PrPicFile procedure to complete a deferred printing. There is no special Printing Manager routine for immediate printing; the routines you use to draw the document in the printing grafPort print the document immediately. 1PrOpenDoc Use the PrOpenDoc function to initialize a printing grafPort for use in printing a document, make it the current port, and return a pointer to it.FUNCTION PrOpenDoc (hPrint: THPrint; pPrPort: TPPrPort; pIOBuf: Ptr): TPPrPort;hPrint The handle to a print record, which may be a new record or an existing one from a document.pPrPort A pointer to the printing grafPort. This parameter should be NIL, which means that PrOpenDoc allocates a new printing grafPort in the heap. pIOBuf A pointer to an area of memory to be used as an input/output buffer. This parameter should be NIL, which means that PrOpenDoc uses the volume buffer for the spool file’s volume. If you allocate your own buffer, it must be 522 bytes exactly. DESCRIPTIONDepending on the setting of the bJDocLoop field in the printing job subrecord, the Printing Manager sets up the printing grafPort for immediate or deferred printing. For deferred printing, it takes the spool file’s name, volume reference number, and version number from the printing job subrecord. Because both the printing grafPort and input/output buffer are nonrelocatable objects, you may want to allocate them yourself using the pPrPort and pIOBuf parameters, to avoid fragmenting the heap. You must balance a call to PrOpenDoc with a call to PrCloseDoc.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrOpenDoc function is $04000C00. Trap macro Trap_PrGlue $A8FDSEE ALSOFor an example of a printing loop, see Listing 1-1 beginning on page 1-12. 1PrCloseDoc Use the PrCloseDoc procedure to close the printing grafPort data type. PROCEDURE PrCloseDoc (pPrPort: TPPrPort);pPrPort A pointer to the printing grafPort data type. DESCRIPTIONFor immediate printing, the PrCloseDoc procedure ends the printing job.For deferred printing, PrCloseDoc ends the deferment: the document must now be printed. Before printing the document, call the PrError procedure to find out whether spooling succeeded. If it did, unload unused code segments to ensure that you have as much memory as possible in which to print and then call PrPicFile. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrCloseDoc procedure is $08000484. Trap macro Trap_PrGlue $A8FDSEE ALSOFor an example of a printing loop, see Listing 1-1 beginning on page 1-12. 1PrOpenPage Use the PrOpenPage procedure to begin a new page. PROCEDURE PrOpenPage (pPrPort: TPPrPort; pPageFrame: TPRect);pPrPort A pointer to the printing grafPort. pPageFrame For deferred printing, a pointer to a rectangle to be used as the QuickDraw picture frame for this page. DESCRIPTIONThe page is printed only if it falls within the page range given in the printing job subrecord. If the user has chosen deferred printing, the Printing Manager scales the rectangle named by the pPageFrame parameter (with the QuickDraw procedure DrawPicture) to coincide with the rectangle specified by rPage in the printer information subrecord. Unless you want the printout to be scaled, you should set pPageFrame to NIL—this uses the rPage rectangle as the picture frame, so that the page is printed with no scaling.You must balance every call to PrOpenPage with a call to PrClosePage. SPECIAL CONSIDERATIONSThe printing grafPort is completely reinitialized by PrOpenPage. Therefore, you must set grafPort features such as the font family and font size for every page that you draw after you call this procedure.Don’t call the QuickDraw function OpenPicture while a page is open (after a call to PrOpenPage but before calling PrClosePage). You can, however, call DrawPicture at any time.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrOpenPage procedure is $10000808. Trap macro Trap_PrGlue $A8FDSEE ALSOFor an example of a printing loop, see Listing 1-1 beginning on page 1-12. 1PrClosePage Use the PrClosePage procedure to finish the printing of the current page. PROCEDURE PrClosePage (pPrPort: TPPrPort);pPrPort A pointer to the printing grafPort. DESCRIPTIONPrClosePage tells the Printing Manager that you are finished with this page, so that the printer driver can do whatever is required (such as release temporary memory) for the current printer in order to avoid communication difficulties or other problems that may cause the user’s computer to crash. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrClosePage procedure is $1800040C. Trap macro Trap_PrGlue $A8FDSEE ALSOFor an example of a printing loop, see Listing 1-1 beginning on page 1-12. 1PrPicFile Use the PrPicFile procedure to complete deferred printing. PROCEDURE PrPicFil (hPrint: THPrint; pPrPort: TPPrPort; pIOBuf: Ptr; pDevBuf: Ptr; VAR prStatus: TPrStatus);hPrint The handle to the specified print record, which may be a new record or an existing one from a document.pPrPort A pointer to the printing grafPort. This parameter should be NIL, which means that PrPicFile should allocate a new printing grafPort in the heap. pIOBuf A pointer to an area of memory to be used as an input/output buffer. This parameter should be NIL, which means that PrPicFile should use the volume buffer for the spool file’s volume. If you allocate your own buffer, it must be 522 bytes exactly. pDevBuf A pointer to a device-dependent buffer. This parameter should be NIL, which means that PrPicFile should allocate a buffer in the heap. prStatus A printing status record that PrPicFile uses to report on its progress: current page number, current copy, or current file being spooled. You can then display this information to the user. The TPrStatus data type is described on page 1-33. DESCRIPTIONIf the user has chosen deferred printing (for example, to get high-quality output on the ImageWriter printer), your application should normally call PrPicFile after PrCloseDoc.SPECIAL CONSIDERATIONSBe sure not to pass, in the pPrPort parameter, a pointer to the same printing grafPort you received from PrOpenDoc. If that port was allocated by PrOpenDoc itself (that is, if the pPrPort parameter to PrOpenDoc was NIL), then PrCloseDoc will have disposed of the port, making your pointer to it invalid. Of course, if you earlier provided your own storage in PrOpenDoc, there’s no reason you can’t use the same storage again for PrPicFile.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrPicFile procedure is $60051480. Trap macro Trap_PrGlue $A8FDOptimizing PrintingThe PrGeneral procedure is a multipurpose routine that allows your application to achieve the highest resolution print output on the current printer, verify page orientation, and increase performance by avoiding deferred printing. In order to select which action you want, you pass an opcode in the iOpcode field of the pData parameter of the procedure. The pData parameter can point to one of four records: TGetRslBlk (page 1-35), TSetRslBlk (page 1-37), TGetRotnBlk (page 1-38), and TDftBitsBlk (page 1-38). All of these records are based on the TGnlData record (page 1-35), so the first three fields of each are identical. Before using the PrGeneral procedure, you should determine whether the current printer driver supports it. See “Checking for PrGeneral” on page 1-16.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrGeneral procedure is $70070480. Trap macro Trap_PrGlue $A8FD1PrGeneral With the GetRslDataOp Opcode Use the PrGeneral procedure with the value GetRslDataOp for the iOpcode field of the parameter block when you want to determine the resolutions available to the current printer. PROCEDURE PrGeneral (pData: Ptr);pData A pointer to the TGetRslBlk record (page 1-35). DESCRIPTIONAfter you call to the PrGeneral procedure with the GetRslDataOp opcode, you should check the value in the iError field of the TGetRslBlk record. The possible result codes are listed below. You should also call PrError (which returns the result code left by the last Printing Manager routine) after checking the iError field, to be sure that no additional errors were generated. RESULT CODESnoErr 0 No errorOpNotImpl 2 Printer driver does not support this opcodeSEE ALSOSee Listing 1-4 on page 1-19 for an example of how to use the GetRslDataOp opcode to determine what printer resolutions are available for the current printer.1PrGeneral With the SetRslOp Opcode Use the PrGeneral procedure with the value SetRslOp for the iOpcode field of the parameter block when you want to set the resolution the current printer. PROCEDURE PrGeneral (pData: Ptr);pData A pointer to the TSetRslBlk record (page 1-37). DESCRIPTIONAfter you call the PrGeneral procedure with the SetRslOp opcode, you should check the value in the iError field of the TSetRslBlk record. The possible result codes are listed below. You should also call PrError (which returns the result code left by the last Printing Manager routine) after checking the iError field, to be sure that no additional errors were generated. RESULT CODESnoErr 0 No errorNoSuchRsl 1 Requested resolution not supported by the currently selected printerOpNotImpl 2 Printer driver does not support this opcodeSEE ALSOSee Listing 1-4 on page 1-19 for an example of how to use the SetRslOp opcode to set the resolution for the current printer.1PrGeneral With the GetRotnOp Opcode Use the PrGeneral procedure with the value GetRotnOp for the iOpcode field of the parameter block when you want to determine if the user has chosen landscape orientation in the style dialog box. PROCEDURE PrGeneral (pData: Ptr);pData A pointer to a TGetRotnBlk record (page 1-38). DESCRIPTIONAfter you call the PrGeneral procedure with the GetRotnOp opcode, you should check the value in the iError field of the TGetRotnBlk record. The possible result codes are listed below. You should also call PrError (which returns the result code left by the last Printing Manager routine) after checking the iError field, to be sure that no additional errors were generated. RESULT CODESnoErr 0 No errorOpNotImpl 2 Printer driver does not support this opcodeSEE ALSOSee Listing 1-5 on page 1-21 for an example of using the GetRotnOp opcode to determine if the user has selected landscape orientation.1PrGeneral With the DraftBitsOp and NoDraftBitsOp Opcodes Use the PrGeneral procedure with the value DraftBitsOp for the iOpcode field of the parameter block when you want to force draft-quality printing. The NoDraftBitsOp opcode cancels the use of draft-quality printing. PROCEDURE PrGeneral (pData: Ptr);pData A pointer to a TDftBitsBlk record (page 1-38). DESCRIPTIONAfter you call the PrGeneral procedure with the DraftBitsOp opcode, you should check the value in the iError field of the TDftBitsBlk record. The possible result codes are listed below. You should also call PrError (which returns the result code left by the last Printing Manager routine) after checking the iError field, to be sure that no additional errors were generated. RESULT CODESnoErr 0 No errorOpNotImpl 2 Printer driver does not support this opcodeSEE ALSOSee “Choosing Draft-Quality Printing” on page 1-21 for more information on using the DraftBitsOp and NoDraftBitsOp opcodes to force the use of or to cancel the use of draft-quality printing.Error HandlingThe PrError function returns the result code left by the last Printing Manager routine. The PrSetError procedure lets you set the value of the current Printing Manager error. 1PrError You can get the result code returned by the last Printing Manager routine from the PrError function. FUNCTION PrError: Integer;DESCRIPTIONIf an error that does not belong to the Printing Manager occurs, the Printing Manager puts it into low memory, where it can be retrieved with a call to PrError, and then terminates the printing loop, if necessary. If you encounter an error in the middle of a printing loop, do not end printing abruptly; call the close routines for any open routines you have already made and let the Printing Manager terminate properly. The Printing Manager returns the following general errors: Name Result Code DescriptioniPrAbort 128 Application or user requested cancelnoErr 0 No erroriPrSavPFil –1 Saving print filecontrolErr –17 Unimplemented control instructionsiIOAbort –27 I/O erroriMemFullErr –108 Not enough room in the heap zoneresNotFound –192 The printer does not support the PrGeneral procedureThe Device Manager returns the controlErr result code. The following result codes are specific to the LaserWriter printer family:Result Code Description–8133 PostScript error occurred during transmission of data to printer. Most often caused by a bug in the PostScript code being downloaded.–8132 Timeout occurred (no communication has occurred with the printer for 2 minutes. Usually caused by extremely long imaging time.–8131 Printer not responding; it may have been turned off. This error occurs if a user turns off the LaserWriter printer in the middle of a print job.–4101 Printer not found or closed.–4100 Connection closed.–4099 Write request too big.–4098 Request already active.–4097 Bad connection refnum.–4096 No free Connect Control Blocks (CCBs) availableIf PrError returns resNotFound after you call the PrGeneral procedure, the current printer driver does not support the PrGeneral procedure. You should clear this error with a call to the PrSetError procedure, with a parameter of 0; otherwise, PrError might still contain this error next time you check it. The following errors are specific to thePrGeneral procedure:Name Result Code DescriptionNoSuchRsl 1 Requested resolution is not supportedOpNotImpl 2 Requested PrGeneral opcode not implemented in the current printer driver.resNotfound –192 The current printer driver does not support PrGeneral.The most common error encountered is –4101, which is generated if no LaserWriter printer is selected. Since this error is so common, it is a good idea to display a dialog box requesting the user to select a printer from the Chooser when this error is encountered.ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrError function is $BA000000. Trap macro Selector_PrGlue $A8FDSEE ALSOSee the section “Handling Printing Errors” on page 1-28 for more information on using PrError. 1PrSetError You can use the PrSetError procedure to set the value of the current printing result code.PROCEDURE PrSetError(iErr: Integer);iErr The value of the result code.DESCRIPTIONPrSetError stores the specified value into the global variable PrintErr where the Printing Manager keeps its result code. You can use PrSetError to cancel a printing operation.If PrError <> noErr THEN PrSetError(iPrAbort)ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrSetError function is $C0000200. Trap macro Trap_PrGlue $A8FDLow-Level RoutinesIn general, you should use the high-level routines of the Printing Manager in preference to the low-level routines. Low-level calls are not guaranteed to work in future versions of the system software in precisely the same manner as they have in past versions of the software. Low-level routines are primarily suited for functions such as text streaming (the process of receiving data from a source and printing it immediately, without any intermediate formatting). In addition, if you use the low-level routines and the user prints a document on a LaserWriter printer, the LaserWriter printer driver translates all low-level calls to the matching high-level ones, so your application does not gain a speed advantage. You should not use both the high-level and low-level routines at the same time (that is, when one or the other interface has opened the printer driver). The only exception to this is that you may use the PrDrvrVers function (page 1-58) with the high-level routines.<36pt\>\x12 <8bat\>s1PrDrvrOpen The PrDrvrOpen procedure opens the printer driver, reading it into memory if necessary. PROCEDURE PrDrvrOpen;DESCRIPTIONUse the PrDrvrOpen procedure with the PrDrvrClose procedure. Do not mix the open and close routines for the low-level interface with the routines from the high-level interface. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrDrvrOpen procedure is $80000000. Trap macro Trap_PrGlue $A8FD1PrDrvrClose The PrDrvrClose procedure closes the printer driver, releasing the memory it occupies. PROCEDURE PrDrvrClose;ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrDrvrClose procedure is $88000000. Trap macro Trap_PrGlue $A8FD1PrDrvrDCE PrDrvrDCE returns a handle to the printer driver’s device control entry (DCE). FUNCTION PrDrvrDCE: Handle;DESCRIPTIONThe printer driver’s device control entry contains specific information about that printer driver. You can also get a handle to the driver’s DCE by calling the Device Manager function GetDCtlEntry. For more information about device control entries and how the Device Manager uses them, see the chapter “Device Manager” in the Inside Macintosh: <italics\>Devices. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrDrvrDCE function is $94000000. Trap macro Trap_PrGlue $A8FD1PrDrvrVers PrDrvrVers returns the version number of the printer driver in the system resource file. FUNCTION PrDrvrVers: Integer;DESCRIPTIONThe version number of the printer driver is available as the predefined constant iPrRelease. You may want to compare the result of PrDrvrVers with iPrRelease to see if the printer driver in the resource file is the most recent version. This is the only low-level printing function you may call from the high-level interface. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrDrvrVers function is $9A000000. Trap macro Trap_PrGlue $A8FDLow-Level Control CallsThe PrCtlCall procedure calls the printer driver’s control routine. Instead of sending the low-level calls to the device driver, the PrCtlCall procedure converts the call into its high-level equivalent before execution. ASSEMBLY LANGUAGE INFORMATIONThe routine selector for the PrCtlCall procedure is $A0000E00. Trap macro Trap_PrGlue $A8FD1PrCtlCall With the iPrBitsCtl Control Constant You can use the PrCtlCall procedure with the iPrBitsCtl control constant when you want to print bitmaps. PROCEDURE PrCtlCall (iWhichCtl: Integer; lParam1: LongInt; lParam2: LongInt; lParam3: LongInt);iWhichCtl The constant iPrBitsCtl. This constant allows you to send all or part of a QuickDraw bitmap directly to the printer.lParam1 A pointer to the QuickDraw bitmap.lParam2 A pointer to the rectangle you want to print.lParam3 The type of resolution used to print the bitmap. The LaserWriter printer driver ignores this flag. This parameter can have one of the following values:Constant Value DescriptionlScreenBits $00000000 The resolution is 80 ¥ 72.lPaintBits $00000001 The resolution is 72 ¥ 72.lHiScreenBits $00000002 The resolution is 160 ¥ 144.lHiPaintBits $00000003 The resolution is 144 ¥ 144.1PrCtlCall With the iPrIOCtl Control Constant You can use the PrCtlCall procedure with the iPrIOCtl control constant when you want text streaming in your application. Text streaming is useful for fast printing of text when speed is more important than visual fidelity or formatting. It makes no use of QuickDraw. PROCEDURE PrCtlCall (iWhichCtl: Integer; lParam1: LongInt; lParam2: LongInt; lParam3: LongInt);iWhichCtl The constant iPrIOCtl. This constant causes text streaming to occur. lParam1 A pointer to the beginning of the text. lParam2 The number of bytes to transfer. The high-order word must be 0. lParam3 This should be 0. 1PrCtlCall With the iPrEvtCtl Control Constant You can use the PrCtlCall procedure with the iPrEvtCtl control constant for printing the screen or the topmost window on an ImageWriter printer. The LaserWriter printer driver does not support this call. PROCEDURE PrCtlCall (iWhichCtl: Integer; lParam1: LongInt; lParam2: LongInt; lParam3: LongInt);iWhichCtl The constant iPrEvtCtl. This constant prints the object you have selected using the lParam1 parameter. lParam1 This parameter selects the object to be printed. If this value is $00000000, you want to print the screen. If this value is $00010000, you want to print the topmost window. lParam2 This should be NIL. lParam3 This should be NIL. 1PrCtlCall with the iPrDevCtl Control Constant You can use the PrCtlCall procedure with the iPrDevCtl control constant for controlling the printer device.PROCEDURE PrCtlCall(iWhichCtl: Integer;lParam1: LongInt;lParam2: LongInt; lParam3: LongInt);iWhichCtl The constant iPrDevCtl. lParam1 The action you want to take. The values possible for this parameter are listed below. lParam2 This should be NIL. lParam3 This should be NIL. DESCRIPTIONYou can specify the following values for the lParam1 parameter:Constant Value DescriptionlPrDocOpen $00010000 Opens the document.This is similar to the high-level call PrOpenDoc and should be followed with a call to PrCtlCall with the iPrDevCtl control call and a param1 value of lPrDocClose. lPrReset $00010000 Reserved by Apple.lPrPageClose $00020000 Closes the page. This is similar to the high-level call PrClosePage and should follow a call to PrCtlCall with the iPrDevCtl control call and a param1 value of lPrPageOpen. lPrPageEnd $00020000 Reserved by Apple. lPrLineFeed $00030000 Paper advance. lPrLFStd $0003FFFF Carriage return with line feed. The ImageWriter printer driver causes a carriage return plus a paper feed of 1/6th of an inch. The LaserWriter printer driver moves the pen location down the page. lPrPageOpen $00040000 Opens the page for printing. This is similar to the high-level call PrOpenPage and should be followed with a call to PrCtlCall with the iPrDevCtl control call and a param1 value of lPrPageClose. lPrDocClose $00050000 Closes the document. This is similar to the high-level call PrCloseDoc and should follow a call to PrCtlCall with the iPrDevCtl control call and a param1 value of lPrDocOpen. SummaryConstantsCONST iPFMaxPgs = 128; iPrPgFract = 120; {Page scale factor. ptPgSize (below) is in units of 1/iPrPgFract} iPrPgFst = 1; {Page range constants} iPrPgMax = 9999; iPrRelease = 3; {Current version number of the code.} iPrSavPFil = -1; iPrAbort = $0080; iPrDevCtl = 7; {The PrDevCtl proc's ctl number} lPrReset = $00010000; {The PrDevCtl proc's CParam for reset} lPrLineFeed = $00030000; lPrLFStd = $0003FFFF; {The PrDevCtl proc's CParam for std paper advance} lPrLFSixth = $0003FFFF; lPrPageEnd = $00020000; {The PrDevCtl proc's CParam for end page} lPrDocOpen = $00010000; lPrPageOpen = $00040000; lPrPageClose = $00020000; lPrDocClose = $00050000; iFMgrCtl = 8; {The File Mgr's tail-hook Proc's ctl number} iMemFullErr = -108; iIOAbort = -27; pPrGlobals = $00000944; {The PrVars low memory area} bDraftLoop = 0; bSpoolLoop = 1; bUser1Loop = 2; bUser2Loop = 3; iPrBitsCtl = 4; lScreenBits = 0; lPaintBits = 1; lHiScreenBits = $00000002; {The Bitmap Print proc's Screen Bitmap param} lHiPaintBits = $00000003; {The Bitmap Print proc's Paint [sq pix] param} iPrIOCtl = 5; iPrEvtCtl = 6; {The PrEvent proc's ctl number} lPrEvtAll = $0002FFFD; {The PrEvent Proc's CParam for the entire screen} lPrEvtTop = $0001FFFD; {The PrEvent Proc's CParam for the top folder} iPrDrvrRef = -3; getRslDataOp = 4; setRslOp = 5; draftBitsOp = 6; noDraftBitsOp = 7; getRotnOp = 8; NoSuchRsl = 1; RgType1 = 1;Data TypesTYPE TFeed = (feedCut,feedFanfold,feedMechCut,feedOther); TScan = (scanTB,scanBT,scanLR,scanRL); TPRect = ^Rect; { A Rect Ptr } PrIdleProcPtr = ProcPtr; PItemProcPtr = ProcPtr; TPPrPort = ^TPrPort; TPrPort = RECORD gPort: GrafPort; {The Printer's graf port.} gProcs: QDProcs; {..and its procs} lGParam1: LongInt; {16 bytes for private parameter storage.} lGParam2: LongInt; lGParam3: LongInt; lGParam4: LongInt; fOurPtr: Boolean; {Whether the PrPort allocation was done by us.} fOurBits: Boolean; {Whether the BitMap allocation was done by us.} END; TPPrInfo = ^TPrInfo; TPrInfo = RECORD iDev: Integer; {Font Mgr/QuickDraw device code} iVRes: Integer; {Resolution of device, in device coordinates} iHRes: Integer; {..note: V before H => compatable with Point.} rPage: Rect; {The page (printable) rectangle in device coordinates.} END; TPPrStl = ^TPrStl; TPrStl = RECORD wDev: Integer; iPageV: Integer; iPageH: Integer; bPort: SignedByte; feed: TFeed; END;TPPrJob = ^TPrJob;TPrJob = RECORD iFstPage: Integer; {Page range} iLstPage: Integer; iCopies: Integer; {Number of copies.} bJDocLoop: SignedByte; {The printing method: immediate or spooled} fFromUsr: Boolean; {Printing from an user's app (not PrApp) flag} pIdleProc: PrIdleProcPtr; {The proc called while application sends document to printer} pFileName: StringPtr; {Spool filename: NIL for default.} iFileVol: Integer; {Spool file vol, set to 0 initially} bFileVers: SignedByte; {Spool file version, set to 0 initially} bJobX: SignedByte; {An extra byte.} END;TPPrint = ^TPrint;THPrint = ^TPPrint;TPrint = RECORD iPrVersion: Integer; {(2) Printing software version} prInfo: TPrInfo; {the printer information subrecord} rPaper: Rect; {the paper rectangle [offset from rPage]} prStl: TPrStl; {information from the style dialog box} prInfoPT: TPrInfo; {(14) Print Time Imaging metrics} prXInfo: TPrXInfo;{Reserved} prJob: TPrJob; {information from the job dialog box} printX: ARRAY [1..19] OF Integer; {Reserved} END;{ The universal 120 byte printing record }TPPrStatus = ^TPrStatus;TPrStatus = RECORD iTotPages: Integer; {Total pages in Print File.} iCurPage: Integer; {Current page number} iTotCopies: Integer; {Total copies requested} iCurCopy: Integer; {Current copy number} iTotBands: Integer; {Total bands per page.} iCurBand: Integer; {Current band number} fPgDirty: Boolean; {True if current page has been written to.} fImaging: Boolean; {Set while in band's DrawPic call.} hPrint: THPrint; {Handle to the active Printer record} pPrPort: TPPrPort; {Ptr to the active PrPort} hPic: PicHandle; {Handle to the active Picture} END;{ PicFile = a TPfHeader followed by n QuickDraw Pics (whose PicSize is invalid!) }TPPrDlg = ^TPrDlg;TPrDlg = RECORD Dlg: DialogRecord; {Ptr to the dialog box} pFltrProc: ModalFilterProcPtr; {The dialog event filter} pItemProc: PItemProcPtr; {The Item evaluating proc.} hPrintUsr: THPrint; {The print record} fDoIt: Boolean; {Dialog box confirmed} fDone: Boolean; {User’s interaction completed} lUser1: LongInt; {Storage for your application} lUser2: LongInt; {Storage for your application} lUser3: LongInt; {Storage for your application} lUser4: LongInt; {Storage for your application} END;PDlgInitProcPtr = ProcPtr;TGnlData = RECORD iOpCode: Integer; iError: Integer; lReserved: LongInt; {more fields here depending on call} END;TGetRslBlk = RECORD iOpCode: Integer; iError: Integer; lReserved: LongInt; iRgType: Integer; xRslRg: TRslRg; yRslRg: TRslRg; iRslRecCnt: Integer; rgRslRec: ARRAY [1..27] OF TRslRec; END;TRslRg = RECORD iMin: Integer; iMax: Integer; END;TRslRec = RECORD iXRsl: Integer; iYRsl: Integer; END;TSetRslBlk = RECORD iOpCode: Integer; iError: Integer; lReserved: LongInt; hPrint: THPrint; iXRsl: Integer; iYRsl: Integer; END;TDftBitsBlk = RECORD iOpCode: Integer; iError: Integer; lReserved: LongInt; hPrint: THPrint; END;TGetRotnBlk = RECORD iOpCode: Integer; iError: Integer; lReserved: LongInt; hPrint: THPrint; fLandscape: Boolean; bXtra: SignedByte; END;RoutinesOpening and Closing the Printing ManagerPROCEDURE PrOpen;PROCEDURE PrClose;Filling and Verifying Print Records PROCEDURE PrintDefault (hPrint: THPrint);FUNCTION PrValidate (hPrint: THPrint): Boolean;Displaying and Customizing the Printing Dialog Boxes FUNCTION PrStlDialog (hPrint: THPrint): Boolean;FUNCTION PrJobDialog (hPrint: THPrint): Boolean;FUNCTION PrDlgMain (hPrint: THPrint; pDlgInit: PDlgInitProcPtr): Boolean;FUNCTION PrStlInit (hPrint: THPrint): TPPrDlg;FUNCTION PrJobInit (hPrint: THPrint): TPPrDlg;PROCEDURE PrJobMerge (hPrintSrc: THPrint; hPrintDst: THPrint);PrintingFUNCTION PrOpenDoc (hPrint: THPrint; pPrPort: TPPrPort; pIOBuf: Ptr): TPPrPort;PROCEDURE PrCloseDoc (pPrPort: TPPrPort);PROCEDURE PrOpenPage (pPrPort: TPPrPort; pPageFrame: TPRect);PROCEDURE PrClosePage (pPrPort: TPPrPort);PROCEDURE PrPicFile (hPrint: THPrint;pPrPort: TPPrPort; pIOBuf: Ptr; pDevBuf: Ptr; VAR prStatus: TPrStatus);Optimizing PrintingPROCEDURE PrGeneral (pData: Ptr);Error HandlingFUNCTION PrError: INTEGER;PROCEDURE PrSetError (iErr: INTEGER);Low-Level RoutinesPROCEDURE PrDrvrOpen;PROCEDURE PrDrvrClose;FUNCTION PrDrvrDCE: Handle;FUNCTION PrDrvrVers: INTEGER;Low-Level Control CallsPROCEDURE PrCtlCall (iWhichCtl: INTEGER;lParam1: LONGINT;lParam2: LONGINT; lParam3: LONGINT);Assembly-Language InformationTrap Macros Requiring Routine Selectors_PrGlueSelector Routine$C8000000 PrOpen$D0000000 PrClose$20040480 PrintDefault$52040498 PrValidate$2A040484 PrStlDialog$32040488 PrJobDialog$4A040894 PrDlgMain$3C04040C PrStlInit$44040410 PrJobInit$5804089C PrJobMerge$04000C00 PrOpenDoc$08000484 PrCloseDoc$10000808 PrOpenPage$1800040C PrClosePage$60051480 PrPicFile$BA000000 PrError$C0000200 PrSetError$70070480 PrGeneral$94000000 PrDrvrDCE$9A000000 PrDrvrVers$80000000 PrDrvrOpen$88000000 PrDrvrClose$A0000E00 PrCtlCallIndexBbackground procedurewriting25 to 26Ddeferred printing4dialog event filtersPrinting Manager23discrete resolution5dots per inch5draft printing, See immediate printingdraft-quality printing4Hhigh-quality printing4Iidle procedure9definition8 to 9immediate printingJjob dialog box (for printing)7job subrecordPpage rectangle4paper rectangle4PrClose procedure40PrCloseDoc procedure48PrClosePage procedure49PrCtlCall procedureiPrBitsCtl control constant58iPrDevCtl control constant60iPrEvtCtl control constant59iPrIOCtl control constant59PrDlgMain function44PrDrvrClose procedure57PrDrvrDCE function57PrDrvrOpen procedure56PrDrvrVers function58PrError function54PrGeneral procedure51DraftBitsOp opcode53GetRotnOp opcode53GetRslDataOp opcode51NoDraftBitsOp opcode53SetRslOp opcode52print record7job subrecord8printer information subrecord8PrintDefault procedure42printer driver3printer resource file3printing grafPort6Printing Managerjob dialog box7style dialog box7PrJobDialog function43PrJobInit function45PrJobMerge procedure46PrOpen procedure40PrOpenDoc function47PrOpenPage procedure48PrPicFile procedure50PrSetError procedure56PrStlDialog function43PrStlInit function45PrValidate function41Rresolution of devices5Sspool file4spool printing See deferred printing4style dialog box (for printing)7TTDftBitsBlk data type38TGetRotnBlk data type38TGetRslBlk data type35TGnlData data type35.See also PrGeneral procedure35TPrDlg data type39TPrInfo data type31TPrint data type30.See also print recordTPrJob data type31.See also job subrecordTPrStatus data type33TPrStl data type33TSetRslBlk data type37Vvariable resolution5ñ @ ˇ ˇˇˇˇ @
- ˇ·ˇ‚7^ , Palatino . Ä ( *